电力电子转战数字IC20220704day39——路科实验3c

news/2024/10/19 10:25:28/

报错1:Fatal: C:/Users/zx/Desktop/chenlab0/ch_pkg.sv(246): Illegal virtual interface dereference.

原因:root_test中的set_interface少写了连接到mcdt_mon的语句,也就是mcdt_mon没有接口接入

加上如图

编译tb和pkg两个文件(只编译pkg也会报错,每次都需要编译tb) 

输入命令行vsim -novopt -solvefaildebug work.tb1_chen "+TESTNAME=basic_test"

错误2:输出数据只有1位

 原因:tb文件中把三个输出wire删掉了,所以默认都是只有1位,加回去即可

 问题3:仿真停不下来,id只有1

问题4:没有checker的打印


放弃,不知道哪里出了问题


 重新整理了下结构,增加了mon_mailbox的例化,把通道从1/2/3改成了0/1/2,还是不行。

放弃

代码先存在这里

package ch_pkg;semaphore run_stop_flags=new();//创建这个运行停止的标志存放桶
//**************************************************//
class ch_trans;
//首先,对变量做随机化,加入间隔
//Packed arrays can be made of only the single bit data types (bit, logic, reg), enumerated types, and other packed arrays and packed structures. This also means you cannot have packed arrays of integer types with predefined widths (e.g. a packed array of byte).rand bit [31:0] data[];//数据变成动态数组(合并数组两边都有[]的只能用单比特的数据类型比如bit logic reg、枚举类型)rand int channel_id;rand int pkt_id;rand int data_idle;rand int pkt_idle;bit rsp;local static int object_id=0;//静态变量,一开始就分配了空间且一直存在constraint cstr{soft data.size inside {[4:8]};foreach(data[i])//按一定规律给出数据(伪随机数)data[i]=='h00C0_0000+(this.channel_id<<24)+(this.pkt_id<<8)+i;soft channel_id==0;soft pkt_id==0;data_idle inside{[0:2]};pkt_idle inside{[1:10]};//注意没有加soft,必须实现};//定义变量和约束后,每个类都需要做的是new函数,初始化/例化?function new();object_id++;endfunction//克隆函数,所有变量复制一次function ch_trans clone();ch_trans c =new();//c=new();//这两可以写成一句 ch_trans c = new();c.data       =this.data;c.channel_id =this.channel_id;c.pkt_id     =this.pkt_id;c.data_idle  =this.data_idle;c.pkt_idle   =this.pkt_idle;c.rsp        =this.rsp;return c;endfunctionfunction string sprint();string s;s={s, $sformatf("======ch_trans====")};s={s, $sformatf("ch_trans object content. ")};s={s, $sformatf("object_id=%0d.\n", this.object_id)};foreach(data[i])s={s, $sformatf("data[%0d]=%8x ", i, this.data[i])};s={s, $sformatf("channel_id=%0d .", this.channel_id)};s={s, $sformatf("pkt_id=%0d .", this.pkt_id)};s={s, $sformatf("data_idle=%0d .", this.data_idle)};s={s, $sformatf("pkt_idle=%0d.", this.pkt_idle)};s={s, $sformatf("rsp=%0d.", this.rsp)};s={s, $sformatf("==============\n")};return s;//这里要返回sendfunctionendclass//**************************************************//
class initiator_chen;
virtual interface_chen intf;//virtual表示在子类中会被调用到,声明类的成员变量接口指针必须用virtual
mailbox #(ch_trans) req_mailbox;
mailbox #(ch_trans) rsp_mailbox;//不用例化,只取gen中的用,但要声明local string name;function new(string name="initiator_chen");this.name=name;
endfunctionfunction void set_interface(virtual interface_chen intf);if(intf==null)$error("null, need to be intantiated.");else this.intf=intf;
endfunctiontask run();this.drive();//要加this表示这个class中的drive
endtasktask drive();//取出gen的mb,取完放在哪里?句柄,而且是ch_transch_trans req, rsp;@(posedge intf.rstn)//复位后开始一直执行forever beginthis.req_mailbox.get(req);//先取this.chnl_write(req);//后用rsp=req.clone();//再复制和点亮rsp.rsp=1;this.rsp_mailbox.put(rsp);//最后放end
endtasktask chnl_write (input ch_trans t);//data变成动态数组,要做相应的改变foreach(t.data[i]) begin@(posedge intf.clk);intf.drv_clk.channel_valid<=1'b1;intf.drv_clk.channel_data<=t.data[i];//data要加t.引用@(negedge intf.clk);wait(intf.channel_ready==1'b1);$display("===========initiator=======================\n");$display("%t [%s] sent data %x\n", $time, name, t.data[i]);repeat (t.data_idle) channel_idle();//原来的idle由ch_trans中的data_idle替代endrepeat (t.pkt_idle) channel_idle();
endtasktask channel_idle();@(posedge intf.clk);intf.drv_clk.channel_valid<=1'b0;intf.drv_clk.channel_data<=1'b0;
endtaskendclass //**************************************************//
class generator_chen;rand int pkt_id = -1;rand int channel_id = -1;rand int data_idle = -1;rand int pkt_idle = -1;rand int data_size = -1;rand int ntrans = 10;constraint cstr{soft channel_id == -1;soft pkt_id == -1;soft data_size == -1;soft data_idle == -1;soft pkt_idle == -1;soft ntrans == 10;}mailbox #(ch_trans) req_mailbox;
mailbox #(ch_trans) rsp_mailbox;function new();//例化两个信箱this.req_mailbox=new();this.rsp_mailbox=new();
endfunctiontask run();repeat(ntrans) send_ntrans();run_stop_flags.put();
endtasktask send_ntrans();ch_trans req, rsp;req=new();//想随机化必须先例化?//rsp=new();assert(req.randomize with { local::channel_id>=0  -> channel_id==local::channel_id;local::pkt_id >= 0    -> pkt_id == local::pkt_id;local::data_idle >= 0 -> data_idle == local::data_idle;local::pkt_idle >= 0  -> pkt_idle == local::pkt_idle;local::data_size >0   -> data.size() == local::data_size;})else $fatal("randomization failure");this.pkt_id++;$display(req.sprint());this.req_mailbox.put(req);this.rsp_mailbox.get(rsp);$display(rsp.sprint());//那不就连续打印两次一样的?assert(rsp.rsp)else $error("%0t error response received", $time);
endtaskfunction string sprint();//同名函数,内容不一样string s;s = {s, $sformatf("===========gen=======================")};s = {s, $sformatf("generator_chen object content is as below: \n")};s = {s, $sformatf("ntrans = %0d: \n", this.ntrans)};s = {s, $sformatf("ch_id = %0d: \n", this.channel_id)};s = {s, $sformatf("pkt_id = %0d: \n", this.pkt_id)};s = {s, $sformatf("data_nidles = %0d: \n", this.data_idle)};s = {s, $sformatf("pkt_nidles = %0d: \n", this.pkt_idle)};s = {s, $sformatf("data_size = %0d: \n", this.data_size)};s = {s, $sformatf("=======================================\n")};return s;
endfunctionfunction void post_randomize();//在上面randomize之后马上打印出来string s;s={"after randomization\n", this.sprint()};$display(s);
endfunctionendclass//**************************************************//
typedef struct packed{bit[31:0] data;bit[1:0]  id;} monitor_data;//**************************************************//
class channel_monitor;local string name;local virtual interface_chen intf;mailbox #(monitor_data) mon_mailbox;function new(string name="channel_monitor");this.name=name;this.mon_mailbox=new();endfunctionfunction void set_interface(virtual interface_chen intf);if(intf==null)$error("null");else this.intf=intf;endfunctiontask run();this.mon_trans();endtasktask mon_trans();monitor_data m;forever begin@(posedge intf.clk iff(intf.mon_clk.channel_valid===1'b1 && intf.mon_clk.channel_ready===1'b1));m.data=intf.mon_clk.channel_data;mon_mailbox.put(m);$display("%0t channel_monitor: %s monitored data %8x", $time, this.name, m.data);endendtaskendclass//**************************************************//
class mcdt_monitor;local string name;local virtual mcdt_chen_interface intf;mailbox #(monitor_data) mon_mailbox;function new(string name="mcdt_monitor");this.name=name;this.mon_mailbox=new();endfunctionfunction void set_interface(virtual mcdt_chen_interface intf);if(intf==null)$error("null");else this.intf=intf;endfunctiontask run();this.mon_trans();endtasktask mon_trans();monitor_data m;forever begin@(posedge intf.clk iff(intf.mon_clk.mcdt_valid===1'b1));m.data=intf.mon_clk.mcdt_data_output;m.id=intf.mon_clk.mcdt_id;mon_mailbox.put(m);$display("%0t %s monitored data %8x and id %0d", $time, this.name, m.data, m.id);endendtask
endclass//**************************************************//	
class checker_chen;
mailbox #(monitor_data) mon_input[3];
mailbox #(monitor_data) mon_output;
local string name;
local int error_count;
local int comp_count;function new(string name="checker_chen");this.name=name;foreach(mon_input[i])this.mon_input[i]=new();this.mon_output=new();this.error_count=0;this.comp_count=0;
endfunctiontask run();this.compare();
endtasktask compare();//typedef的monitor_data也有句柄?monitor_data in, out;forever beginmon_output.get(out);case(out.id)2'd0: mon_input[0].get(in);2'd1: mon_input[1].get(in);2'd2: mon_input[2].get(in);default: $fatal("id %0d is not avalidable", out.id);endcaseif(out.data != in.data) beginthis.error_count++;$error("mcdt_data_output %8x, channel id %0d is not equal with channel in data %8x", out.data, out.id, in.data);endelse begin$display("succeed!!!!!!!!%8x, ____checker_chen_____%0d,= %8x", out.data, out.id, in.data);endthis.comp_count++;end
endtaskendclass//**************************************************//				 
class ch_agent;channel_monitor ch_mon;initiator_chen init;local string name;virtual interface_chen aintf;function new(string name="ch_agent");this.name=name;this.ch_mon=new(name);this.init=new(name);endfunctionfunction void set_interface(virtual interface_chen aintf);this.aintf=aintf;init.set_interface(aintf);ch_mon.set_interface(aintf);endfunctiontask run();forkinit.run();ch_mon.run();joinendtask
endclass //**************************************************//
class root_test;//声明所有句柄ch_agent agent[3];generator_chen gen[3];checker_chen chk;mcdt_monitor mcdt_mon;protected string name;event gen_stop_event;function new(string name="root_test");this.chk=new();//this.mon_mailbox=new();this.name=name;foreach(agent[i]) beginthis.agent[i]=new($sformatf("ch_agent%0d\n", i));//不仅要new,还要给idthis.gen[i]=new();//可以直接和agent共用这个foreachthis.agent[i].init.req_mailbox=this.gen[i].req_mailbox;this.agent[i].init.rsp_mailbox=this.gen[i].rsp_mailbox;this.agent[i].ch_mon.mon_mailbox=this.chk.mon_input[i];endthis.mcdt_mon=new();this.mcdt_mon.mon_mailbox=this.chk.mon_output;$display("%s instantiated and connected objects", this.name );endfunctionvirtual function void do_config();endfunctionvirtual task gen_stop_callback();endtaskvirtual task run_stop_callback();$display("run_stop_callback enterred");$display("%s: wait for all generators have generated and tranferred transcations", this.name);run_stop_flags.get(3);//一开始就例化了$display($sformatf("*****************%s finished********************", this.name));$finish();endtask	virtual task run();$display($sformatf("*****************%s started********************", this.name));this.do_config();forkagent[0].run();agent[1].run();agent[2].run();mcdt_mon.run();chk.run();join_noneforkthis.gen_stop_callback();@(this.gen_stop_event) disable gen_run;join_nonefork: gen_rungen[0].run();gen[1].run();gen[2].run();joinrun_stop_callback();endtaskvirtual function void set_interface(virtual interface_chen intf1,virtual interface_chen intf2,virtual interface_chen intf3,virtual mcdt_chen_interface mcdt_intf);agent[0].set_interface(intf1);agent[1].set_interface(intf2);agent[2].set_interface(intf3);mcdt_mon.set_interface(mcdt_intf);endfunction
endclass//**************************************************//
class basic_test extends root_test;
function new(string name="basic_test");super.new(name);
endfunctionvirtual function void do_config();//root里面给空,virtual多态在这里写具体的super.do_config();assert(gen[0].randomize() with {ntrans==10;data_idle==0;pkt_idle==1;data_size==8;})else $fatal("gen[0] randomization failure");assert(gen[1].randomize() with {ntrans==5;data_idle inside {[1:2]};pkt_idle inside {[3:5]};data_size==6;})else $fatal("gen[1] randomization failure");assert(gen[2].randomize() with {ntrans==8;data_idle inside {[0:1]};pkt_idle inside {[1:2]};data_size==32;})else $fatal("gen[2] randomization failure");
endfunction
endclass: basic_test
//**************************************************//
class burst_test extends root_test;
function new(string name="burst_test");super.new(name);
endfunctionvirtual function void do_config();//root里面给空,virtual多态在这里写具体的super.do_config();assert(gen[0].randomize() with {ntrans inside {[80:100]}; data_idle==0; pkt_idle==1; data_size inside {8, 16, 32};})else $fatal("[RNDFAIL] gen[0] randomization failure!");assert(gen[1].randomize() with {ntrans inside {[80:100]}; data_idle==0; pkt_idle==1; data_size inside {8, 16, 32};})else $fatal("[RNDFAIL] gen[1] randomization failure!");assert(gen[2].randomize() with {ntrans inside {[80:100]}; data_idle==0; pkt_idle==1; data_size inside {8, 16, 32};})else $fatal("[RNDFAIL] gen[2] randomization failure!");
endfunction
endclass: burst_test
//**************************************************//
class full_test extends root_test;
function new(string name="full_test");super.new(name);
endfunctionvirtual function void do_config();super.do_config();assert(gen[0].randomize() with {ntrans inside {[1000:2000]}; data_idle==0; pkt_idle==1; data_size inside {8, 16, 32};})else $fatal("[RNDFAIL] gen[0] randomization failure!");assert(gen[1].randomize() with {ntrans inside {[1000:2000]}; data_idle==0; pkt_idle==1; data_size inside {8, 16, 32};})else $fatal("[RNDFAIL] gen[1] randomization failure!");assert(gen[2].randomize() with {ntrans inside {[1000:2000]}; data_idle==0; pkt_idle==1; data_size inside {8, 16, 32};})else $fatal("[RNDFAIL] gen[2] randomization failure!");
endfunction
//这里报错(vlog-13169) Packed dimension must specify a range.
local function bit[0:2] get_channel_ready_flag();return{agent[0].aintf.mon_clk.channel_ready,agent[1].aintf.mon_clk.channel_ready,agent[2].aintf.mon_clk.channel_ready};//是agent中的接口,命名成了aintf
endfunctionvirtual task gen_stop_callback();bit[0:2] channel_ready_flag;//表示赋值?$display("gen_stop_callback enterred");@(posedge agent[0].aintf.rstn);forever begin@(posedge agent[0].aintf.clk);channel_ready_flag=this.get_channel_ready_flag();if($countones(channel_ready_flag)<1) break;//只剩一个以下的通道不给写入数据了,就break//这个还得再商榷一下end$display("%s: stop 3 generators running", this.name);-> this.gen_stop_event;//这个就是gen_stop的event
endtaskvirtual task run_stop_callback();$display("run_stop_callback enterred");$display("%s: waiting DUT transfering all of data", this.name);forkwait(agent[0].aintf.slave_margin=='h0);wait(agent[1].aintf.slave_margin=='h0);wait(agent[2].aintf.slave_margin=='h0);join$display("%s: 3 channel fifos have transferred all data", this.name);$display($sformatf("*****************%s finished********************", this.name));$finish();
endtaskendclass: full_test//**************************************************//
endpackage :ch_pkg
//**************************************************//
`timescale 1ns/1ps
//*********************接口多了个mcdt的,monitor也需要时钟块**************************//
interface interface_chen (input clk, input rstn);logic [31:0] channel_data;
logic        channel_valid;
logic        channel_ready;
logic [ 7:0] slave_margin;clocking drv_clk @(posedge clk);default input #1ns output #1ns;input  channel_ready, slave_margin;//采样output channel_data, channel_valid;//驱动
endclocking 
//定义了monitor的时钟块
clocking mon_clk @(posedge clk);default input #1ns output #1ns;input channel_ready, slave_margin, channel_data, channel_valid;
endclockingendinterface interface mcdt_chen_interface (input clk, input rstn);
//存放mcdt三个输出,monitor的时钟块
logic [31:0] mcdt_data_output;
logic        mcdt_valid;
logic [ 1:0] mcdt_id;clocking mon_clk @(posedge clk);default input #1ns output #1ns;input mcdt_data_output, mcdt_valid, mcdt_id;//都是input
endclockingendinterface 
//**************************************************//module tb1_chen();//logic          clk;
logic          rstn;
//原来的3个mcdt输出变成了接口
wire [31:0] mcdt_data_output;
wire        mcdt_valid;
wire [ 1:0] mcdt_id;mcdt_chen dut(//括号里面的信号变成接口里面的.clk(clk),.rstn(rstn),.channel0_data(ch0_intf.channel_data)//信号改为接口中的名称,.channel0_valid(ch0_intf.channel_valid),.slave0_margin(ch0_intf.slave_margin),.channel0_ready(ch0_intf.channel_ready),.channel1_data(ch1_intf.channel_data),.channel1_valid(ch1_intf.channel_valid),.channel1_ready(ch1_intf.channel_ready),.slave1_margin(ch1_intf.slave_margin),.channel2_data(ch2_intf.channel_data),.channel2_valid(ch2_intf.channel_valid),.channel2_ready(ch2_intf.channel_ready),.slave2_margin(ch2_intf.slave_margin),.mcdt_data_output(mcdt_data_output),.mcdt_valid(mcdt_valid),.mcdt_id(mcdt_id)
);//*****************clk和rstn******************************//
task clk_gen(input int T);clk <= 0;forever begin#(T/2) clk<= !clk;end
endtaskinitial beginclk_gen(10);
endtask rstn_gen();#10 rstn <= 0;repeat(10) @(posedge clk);rstn <= 1;
endtaskinitial beginrstn_gen();
endimport ch_pkg::*;//引入包中所有的类 //**************************************************//
basic_test b1;
burst_test b2;
full_test  b3;
root_test test[string];
string name;//**************接口************************//
interface_chen ch0_intf(.*);
interface_chen ch1_intf(.*);
interface_chen ch2_intf(.*);
mcdt_chen_interface mcdt_intf(.*);initial beginb1=new();b2=new();b3=new();test["basic_test"]=b1;test["burst_test"]=b2;test["full_test"]=b3;if($value$plusargs("TESTNAME=%s", name)) beginif(test.exists(name)) begin//函数exists()来检查元素是否存在。test[name].set_interface(ch0_intf, ch1_intf, ch2_intf, mcdt_intf);test[name].run();endelse begin$fatal($sformatf("[ERRTEST], test name %s is invalid, please specify a valid name!", name));endendelse begin$display("NO runtime optiont +TESTNAME=xxx is configured, and run default test chnl_basic_test");test["basic_test"].set_interface(ch0_intf, ch1_intf, ch2_intf, mcdt_intf);test["basic_test"].run();end
endendmodule  


http://www.ppmy.cn/news/902156.html

相关文章

大专的电子信息工程技术学什么?

这个问题应该困惑不少选了这个专业的同学&#xff0c;今天我为大家解读。每个学校课程不同&#xff0c;大体方向是这样。 主要内容&#xff1a;物联网 大家可能心里会想&#xff0c;这不是很符合当今的热门话题嘛&#xff01; 别急&#xff0c;继续往下看。 大家从电子信息…

对口集成电路专业----微电子科学与工程

很多同学在向我咨询就业班课程的时候&#xff0c;都会比较担心自己的专业是否对口&#xff0c;对于学完就业班的课程之后&#xff0c;就业会不会有很大的影响&#xff1f; 接下来&#xff0c;给大家梳理了属于科班出身的学生都来源于哪些大学&#xff08;大部分&#xff09;的…

电子科学与技术算计算机相关专业吗,电子科学与技术专业属于什么学科

电子科学与技术专业属于工学类。全国本科专业分为12大学科门类&#xff1a;哲学、经济学、法学、教育学、文学、历史学、理学、工学、农学、医学、管理学、艺术学。 电子科学与技术专业属于什么类专业学历层次门类学科 电子科学与技术本科工学电子信息类 本科十二大类 本科专业…

计算机专业属于文科理科还是工科,电子与计算机工程专业是文科还是理科

电子与计算机工程专业是文科还是理科2018-06-02 14:46:05文/李男 电子与计算机工程专业究竟是文科还是理科呢&#xff1f;电子与计算机工程专业本科毕业后授予的是工学学位&#xff0c;属于计算机类&#xff0c;一般各高校该专业招收理科生。 电子与计算机工程专业是文是理 从专…

什么是电子工程

什么是电子工程 了解电子工程是什么以及它可能涉及哪些职业。 电子工程或电子工程是与电子电路&#xff0c;设备以及使用它们的设备和系统相关的工程形式。 电子工程利用各种不同类型的电子元件&#xff0c;从更传统的模拟元件到数字电子元件&#xff0c;微处理器和微控制器…

高中电子技术——电子元器件的识别

前言&#xff1a;高中电子技术对于元器件的识别考察一般从电子元器件的外观功能、极性或者方向性来考察&#xff0c;下面是一些简单的整理&#xff0c;主要从三个方面入手&#xff1a;极性方向、连接端口数以及功能样式。 1. 电阻 方向&#xff1a;无正负极方向连接端口数&…

电子工程师指从事各类电子设备和信息研究、等工作的工程技术人才

弹人生&#xff0c;弹理想&#xff0c;从模拟电路弹到人生哲学。——电子工程师的自我修养 电子工程师 电子工程师指从事各类电子设备和信息系统研究、教学、产品设计、科技开发、生产和管理等工作的高级工程技术人才。一般分为硬件工程师和软件工程师。硬件工程师是硬件电路原…

TI杯2021年全国大学生电子设计竞赛仪器设备和主要元器件清单

本科组 仪器设备清单 01 数字示波器&#xff08;100MHz&#xff0c;双通道&#xff09; 函数发生器&#xff08;50MHz&#xff0c;双通道&#xff09; 任意波信号发生器&#xff08;1MHz&#xff09; 频谱分析仪&#xff08;1GHz&#xff09; 频率计&#xff08;500MHz&…