System verilog 模拟永远不会结束
我正在尝试在SystemVerilog中学习UVM。我理解UVM的理念,但我很难写出一个工作案例。System verilog 模拟永远不会结束,system-verilog,uvm,System Verilog,Uvm,我正在尝试在SystemVerilog中学习UVM。我理解UVM的理念,但我很难写出一个工作案例。 我想写一个apb测试台。它编译并运行,这对我来说已经是一个胜利,但是监视器接收到的事务具有零值并且是不间断的 我一直在寻找关于这个问题的信息,得出的结论是,这个问题与提出/放弃异议有关 下面是测试类代码,包含以下调用 `include "uvm_macros.svh" import uvm_pkg::*; class apb_test extends uvm_test; `uvm_comp
我想写一个apb测试台。它编译并运行,这对我来说已经是一个胜利,但是监视器接收到的事务具有零值并且是不间断的 我一直在寻找关于这个问题的信息,得出的结论是,这个问题与提出/放弃异议有关 下面是测试类代码,包含以下调用
`include "uvm_macros.svh"
import uvm_pkg::*;
class apb_test extends uvm_test;
`uvm_component_utils(apb_test);
apb_env env;
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
begin
apb_configuration apb_cfg;
apb_cfg = new;
assert(apb_cfg.randomize());
uvm_config_db#(apb_configuration)::set(.cntxt(this), .inst_name("*"), .field_name("config"), .value(apb_cfg) );
env = apb_env::type_id::create(.name("env"), .parent(this));
end
endfunction: build_phase
task run_phase(uvm_phase phase);
apb_sequence apb_seq;
phase.raise_objection(.obj(this));
apb_seq = apb_sequence::type_id::create(.name("apb_seq"));
//assert(apb_seq.randomize());
`uvm_info("apb_test", {"\n",apb_seq.sprint()}, UVM_LOW)
apb_seq.start(env.agent.apb_seq);
#10ns;
phase.drop_objection(.obj(this));
endtask: run_phase
endclass: apb_test
整个项目:
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 30.04.2019 17:12:58
// Design Name:
// Module Name: apb_interface
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`include "uvm_macros.svh"
interface apb_if #( ADDR_WIDTH = 3
, SEL_WIDTH = 2
,WRITE_WIDTH = 32
, READ_WIDTH = WRITE_WIDTH
)
(input bit clk, reset_n);
localparam STRB_WIDTH = WRITE_WIDTH%8? (WRITE_WIDTH/8)+1 : WRITE_WIDTH/8;
logic [ADDR_WIDTH:0] addr;
logic [ 2:0] prot;
logic [SEL_WIDTH-1:0] sel;
logic enable;
logic write;
logic [WRITE_WIDTH-1:0] wdata;
logic [STRB_WIDTH-1:0] strb;
logic ready;
logic [READ_WIDTH-1:0] rdata;
logic slv_err;
clocking master_cb @ (posedge clk);
default input #1ns output #1ns;
output addr, prot, sel, enable, write, wdata, strb;
input ready, rdata, slv_err;
endclocking: master_cb
clocking slave_cb @(posedge clk);
default input #1ns output #1ns;
input addr, prot, sel, enable, write, wdata, strb;
output ready, rdata, slv_err;
endclocking: slave_cb
clocking monitor_cb @(posedge clk);
default input #1ns output #1ns;
input addr, prot, sel, enable, write, wdata, strb, ready, rdata, slv_err;
endclocking: monitor_cb
modport master_mp (input clk, reset_n, ready, rdata, slv_err, output addr, prot, sel, enable, write, wdata, strb);
modport slave_mp (input clk, reset_n, addr, prot, sel, enable, write, wdata, strb, output ready, rdata, slv_err);
modport master_sync_mp (clocking master_cb);
modport slave_sync_mp (clocking slave_cb );
endinterface: apb_if
package apb_pkg;
import uvm_pkg::*;
class apb_configuration extends uvm_object;
`uvm_object_utils( apb_configuration )
function new( string name = "" );
super.new( name );
endfunction: new
endclass: apb_configuration
class apb_seq_item #( ADDR_WIDTH = 3
, SEL_WIDTH = 2
,WRITE_WIDTH = 32
, READ_WIDTH = WRITE_WIDTH
) extends uvm_sequence_item;
localparam STRB_WIDTH = WRITE_WIDTH%8? (WRITE_WIDTH/8)+1 : WRITE_WIDTH/8;
`uvm_object_utils(apb_seq_item)
// Control information
rand bit [31:0] addr;
rand bit [ 2:0] prot;
rand bit [SEL_WIDTH-1:0] sel;
rand bit write;
rand bit ready;
// Payload information
rand bit [WRITE_WIDTH-1:0] wdata;
rand bit [STRB_WIDTH-1:0] strb;
// Analysis information
rand bit [READ_WIDTH-1:0] rdata;
rand bit slv_err;
constraint read_constr {
write == 0 -> strb == 0;
}
function new(string name = "apb_seq_item");
super.new(name);
endfunction: new
virtual function void do_copy(uvm_object rhs);
apb_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
uvm_report_error("do_copy:", "Cast failed");
return;
end
super.do_copy(rhs); // Chain the copy with parent classes
addr = rhs_.addr;
prot = rhs_.prot;
sel = rhs_.sel;
write = rhs_.write;
ready = rhs_.ready;
wdata = rhs_.wdata;
strb = rhs_.strb;
rdata = rhs_.rdata;
slv_err = rhs_.slv_err;
endfunction: do_copy
virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
apb_seq_item rhs_;
// If the cast fails, comparison has also failed
// A check for null is not needed because that is done in the compare()
// function which calls do_compare()
if(!$cast(rhs_, rhs)) begin
return 0;
end
return( super.do_compare(rhs,comparer) &&
(addr = rhs_.addr) &&
(prot = rhs_.prot) &&
(sel = rhs_.sel) &&
(write = rhs_.write) &&
(ready = rhs_.ready) &&
(wdata = rhs_.wdata) &&
(strb = rhs_.strb) &&
(rdata = rhs_.rdata) &&
(slv_err= rhs_.slv_err));
endfunction: do_compare
virtual function string convert2string();
string s;
s = super.convert2string();
// Note the use of \t (tab) and \n (newline) to format the data in columns
// The enumerated op_code types .name() method returns a string corresponding to its value
s = {s, $psprintf("\naddr\t\t: %0h",addr)};
s = {s, $psprintf("\nprot\t\t: %0b",prot)};
s = {s, $psprintf("\nsel\t\t: %0b",sel)};
s = {s, $psprintf("\nwrite\t\t: %0b",write)};
s = {s, $psprintf("\nready\t\t: %0b",ready)};
s = {s, $psprintf("\nwdata\t\t: %0h",wdata)};
s = {s, $psprintf("\nstrb\t\t: %0b",strb)};
s = {s, $psprintf("\nrdata\t\t: %0h",rdata)};
s = {s, $psprintf("\nslv_err\t: %0b",slv_err)};
return s;
endfunction: convert2string
virtual function void do_print(uvm_printer printer);
$display(convert2string());
endfunction: do_print
// This implementation is simulator specific.
// In order to get transaction viewing to work with Questa you need to
// Set the recording_detail config item to UVM_FULL:
// set_config_int("*", "recording_detail", UVM_FULL);
virtual function void do_record(uvm_recorder recorder);
super.do_record(recorder); // To record any inherited data members
`uvm_record_field("addr", addr)
`uvm_record_field("prot", prot)
`uvm_record_field("sel", sel)
`uvm_record_field("write", write)
`uvm_record_field("ready", ready)
`uvm_record_field("wdata", wdata)
`uvm_record_field("strb", strb)
`uvm_record_field("rdata", rdata)
`uvm_record_field("slv_err", slv_err)
endfunction: do_record
virtual function void do_pack(uvm_packer packer);
super.do_pack(packer);
`uvm_pack_int(addr);
`uvm_pack_int(prot);
`uvm_pack_int(sel);
`uvm_pack_int(write);
`uvm_pack_int(ready);
`uvm_pack_int(wdata);
`uvm_pack_int(strb);
`uvm_pack_int(rdata);
`uvm_pack_int(slv_err);
endfunction: do_pack
virtual function void do_unpack(uvm_packer packer);
super.do_unpack(packer);
`uvm_unpack_int(addr);
`uvm_unpack_int(prot);
`uvm_unpack_int(sel);
`uvm_unpack_int(write);
`uvm_unpack_int(ready);
`uvm_unpack_int(wdata);
`uvm_unpack_int(strb);
`uvm_unpack_int(rdata);
`uvm_unpack_int(slv_err);
endfunction: do_unpack
endclass: apb_seq_item
class apb_sequence extends uvm_sequence#(apb_seq_item);
`uvm_object_utils(apb_sequence)
function new(string name = "");
super.new(name);
endfunction: new
task body();
apb_seq_item trans;
repeat(2) begin
trans = apb_seq_item#()::type_id::create("ap_it");
start_item(trans);
assert(req.randomize());
finish_item(trans);
end
endtask: body
endclass: apb_sequence
class apb_sequencer extends uvm_sequencer#(apb_seq_item);
`uvm_component_utils(apb_sequencer)
function new(string name, uvm_component parent = null);
super.new(name, parent);
endfunction: new
endclass: apb_sequencer
class apb_driver extends uvm_driver#(apb_seq_item);
`uvm_component_utils(apb_driver)
virtual apb_if apb_vi;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_resource_db#(virtual apb_if)::read_by_name
(.scope("ifs"), .name("apb_if"), .val(apb_vi) ) );
endfunction: build_phase
task run_phase(uvm_phase phase);
apb_seq_item trans;
//super.run_phase(phase);
apb_vi.master_cb.sel <= 0;
apb_vi.master_cb.enable <= 1'b0;
forever begin
seq_item_port.get_next_item(trans);
uvm_report_info("APB_DRIVER ", $psprintf("Got Transaction %s",trans.convert2string()));
@apb_vi.master_cb;
apb_vi.master_cb.addr <= trans.addr;
apb_vi.master_cb.sel <= trans.sel;
apb_vi.master_cb.prot <= trans.prot;
if(trans.write)begin
apb_vi.master_cb.write <= 1'b1;
//apb_vi.master_cb.wdata <= trans.wdata;
apb_vi.master_cb.strb <= trans.strb;
@apb_vi.master_cb;
apb_vi.master_cb.enable <= 1'b1;
// while(!apb_vi.master_cb.ready)begin
// @apb_vi.master_cb;
// end
end
else begin
apb_vi.master_cb.write <= 1'b0;
@apb_vi.master_cb;
apb_vi.master_cb.enable <= 1'b1;
// while(!apb_vi.master_cb.ready)begin
// @apb_vi.master_cb;
// end
trans.rdata <= apb_vi.master_cb.rdata;
trans.slv_err <= apb_vi.master_cb.slv_err;
end
apb_vi.master_cb.sel <= 0;
apb_vi.master_cb.enable <= 1'b0;
seq_item_port.item_done();
end
endtask: run_phase
endclass: apb_driver
class apb_monitor extends uvm_monitor;
`uvm_component_utils(apb_monitor);
uvm_analysis_port#(apb_seq_item) apb_ap;
virtual apb_if apb_vi;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_resource_db#(virtual apb_if)::read_by_name(.scope("ifs"), .name("apb_if"), .val(apb_vi) ) );
apb_ap = new(.name("apb_ap"), .parent(this));
endfunction: build_phase
task run_phase(uvm_phase phase);
forever begin
apb_seq_item trans;
trans = apb_seq_item#()::type_id::create(.name("trans"));
trans.addr <= apb_vi.monitor_cb.addr;
trans.prot <= apb_vi.monitor_cb.prot;
trans.sel <= apb_vi.monitor_cb.sel;
trans.write <= apb_vi.monitor_cb.write;
trans.wdata <= apb_vi.monitor_cb.wdata;
trans.strb <= apb_vi.monitor_cb.strb;
trans.rdata <= apb_vi.monitor_cb.rdata;
trans.slv_err <= apb_vi.monitor_cb.slv_err;
uvm_report_info("APB_MONITOR", $psprintf("Got Transaction %s", trans.convert2string()));
apb_ap.write(trans);
end
endtask: run_phase
endclass: apb_monitor
class apb_agent extends uvm_agent;
`uvm_component_utils(apb_agent)
uvm_analysis_port#(apb_seq_item) apb_ap;
apb_sequencer apb_seq;
apb_driver apb_drv;
apb_monitor apb_mon;
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
apb_ap = new(.name("apb_ap"), .parent(this));
apb_seq = apb_sequencer ::type_id::create(.name("apb_seq"), .parent(this) );
apb_drv = apb_driver ::type_id::create(.name("apb_drv"), .parent(this) );
apb_mon = apb_monitor ::type_id::create(.name("apb_mon"), .parent(this) );
endfunction: build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
apb_drv.seq_item_port.connect(apb_seq.seq_item_export);
apb_mon.apb_ap.connect(apb_ap);
endfunction: connect_phase
endclass: apb_agent
class apb_fc_subs#( ADDR_WIDTH = 3
, SEL_WIDTH = 2
,WRITE_WIDTH = 32
, READ_WIDTH = WRITE_WIDTH
) extends uvm_subscriber#(apb_seq_item);
`uvm_component_utils(apb_fc_subs);
apb_seq_item trans;
covergroup apb_cg;
address: coverpoint trans.addr {
bins low = {0, 1 << ADDR_WIDTH/4 - 1};
bins med = {1 << ADDR_WIDTH/4, 1 << ADDR_WIDTH/2 - 1};
bins high = {1 << ADDR_WIDTH/2, 1 << ADDR_WIDTH - 1};
}
select: coverpoint trans.sel;
prot: coverpoint trans.prot;
wdata: coverpoint trans.wdata;// iff(write);
strb: coverpoint trans.strb;// iff(write);
rw: coverpoint trans.write{
bins read = {0};
bins write = {1};
}
endgroup: apb_cg
function new(string name, uvm_component parent);
super.new(name,parent);
apb_cg = new();
endfunction: new
function void write(apb_seq_item t);
trans = t;
apb_cg.sample();
endfunction: write
endclass: apb_fc_subs
typedef class apb_scoreboard;
class apb_sb_subs extends uvm_subscriber#(apb_seq_item);
`uvm_component_utils(apb_sb_subs)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction: new
function void write(apb_seq_item t);
apb_scoreboard apb_sb;
$cast(apb_sb, m_parent);
apb_sb.apb_check(t);
endfunction: write
endclass: apb_sb_subs
class apb_scoreboard extends uvm_scoreboard;
`uvm_component_utils(apb_scoreboard)
uvm_analysis_export#(apb_seq_item) apb_analysis_export;
local apb_sb_subs sb_sub;
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
apb_analysis_export = new(.name("apb_analysis_export"), .parent(this));
sb_sub = apb_sb_subs::type_id::create(.name("sb_sub"), .parent(this));
endfunction: build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
apb_analysis_export.connect(sb_sub.analysis_export);
endfunction: connect_phase
virtual function void apb_check(apb_seq_item trans);
`uvm_info("SCOREBOARD","Dummy check",UVM_LOW);
endfunction: apb_check
endclass: apb_scoreboard
class apb_env extends uvm_env;
`uvm_component_utils(apb_env)
apb_agent agent;
apb_fc_subs fc_sub;
apb_scoreboard sco;
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent = apb_agent ::type_id::create(.name("agent") , .parent(this));
fc_sub = apb_fc_subs#()::type_id::create(.name("fc_sub") , .parent(this));
sco = apb_scoreboard::type_id::create(.name("sco") , .parent(this));
endfunction: build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
agent.apb_ap.connect(fc_sub.analysis_export);
agent.apb_ap.connect(sco.apb_analysis_export);
endfunction: connect_phase
endclass: apb_env
class apb_test extends uvm_test;
`uvm_component_utils(apb_test);
apb_env env;
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
begin
apb_configuration apb_cfg;
apb_cfg = new;
assert(apb_cfg.randomize());
uvm_config_db#(apb_configuration)::set(.cntxt(this), .inst_name("*"), .field_name("config"), .value(apb_cfg) );
env = apb_env::type_id::create(.name("env"), .parent(this));
end
endfunction: build_phase
task run_phase(uvm_phase phase);
apb_sequence apb_seq;
phase.raise_objection(.obj(this));
apb_seq = apb_sequence::type_id::create(.name("apb_seq"));
//assert(apb_seq.randomize());
`uvm_info("apb_test", {"\n",apb_seq.sprint()}, UVM_LOW)
apb_seq.start(env.agent.apb_seq);
#10ns;
phase.drop_objection(.obj(this));
endtask: run_phase
endclass: apb_test
endpackage: apb_pkg
module apb_memory #( parameter ADDR_WIDTH
,parameter SEL_WIDTH
,parameter WRITE_WIDTH
,parameter READ_WIDTH
)
(apb_if.slave_mp apb_intf);
localparam IDLE = 2'd0;
localparam WRITE= 2'd1;
localparam READ = 2'd2;
bit [1:0] state;
bit [ADDR_WIDTH-1:0]addr;
bit [WRITE_WIDTH-1:0]data[1<<ADDR_WIDTH];
initial begin
state = 0;
end
always@(apb_intf.clk) begin
if(!apb_intf.reset_n) state <= IDLE;
else
case(state)
IDLE: if(apb_intf.sel != 0) begin
if(apb_intf.write)begin
state <= WRITE;
end
else begin
state <= READ;
apb_intf.rdata <= data[apb_intf.addr];
end
apb_intf.ready <= 1;
end
WRITE: if(apb_intf.enable) begin
data[apb_intf.addr] <= apb_intf.wdata;
apb_intf.ready <= 0;
state <= IDLE;
end
READ: if(apb_intf.enable) begin
apb_intf.slv_err <= 0;
state <= IDLE;
end
default: state <= IDLE;
endcase
end
endmodule
module test_bench;
import uvm_pkg::*;
import apb_pkg::*;
parameter ADDR_WIDTH = 3;
parameter SEL_WIDTH = 2;
parameter WRITE_WIDTH = 32;
parameter READ_WIDTH = WRITE_WIDTH;
bit clk,reset;
apb_if #( ADDR_WIDTH
, SEL_WIDTH
,WRITE_WIDTH
, READ_WIDTH
)apb_intf(clk,~reset);
apb_memory #( ADDR_WIDTH
, SEL_WIDTH
,WRITE_WIDTH
, READ_WIDTH
)DUT(apb_intf);
initial begin
clk = 0;
#5ns ;
forever #5ns clk = ! clk;
end
initial begin
uvm_resource_db#( virtual apb_if )::set
( .scope( "ifs" ), .name( "apb_if" ), .val( apb_intf ) );
run_test();
end
endmodule
//////////////////////////////////////////////////////////////////////////////////
//公司:
//工程师:
//
//创建日期:30.04.2019 17:12:58
//设计名称:
//模块名称:apb_接口
//项目名称:
//目标设备:
//工具版本:
//说明:
//
//依赖项:
//
//修订:
//版本0.01-已创建文件
//补充意见:
//
//////////////////////////////////////////////////////////////////////////////////
`包括“uvm_macros.svh”
接口apb_if#(地址宽度=3
,选择宽度=2
,写入宽度=32
,读取宽度=写入宽度
)
(输入位时钟,复位);
localparam STRB_WIDTH=写入宽度%8?(写入宽度/8)+1:写入宽度/8;
逻辑[ADDR\u WIDTH:0]ADDR;
逻辑[2:0]保护;
逻辑[SEL_WIDTH-1:0]SEL;
逻辑使能;
逻辑写入;
逻辑[WRITE_WIDTH-1:0]wdata;
逻辑[STRB_WIDTH-1:0]STRB;
逻辑就绪;
逻辑[READ_WIDTH-1:0]rdata;
逻辑逻辑错误;
时钟主机(posedge时钟);
默认输入#1ns输出#1ns;
输出地址、保护、选择、启用、写入、wdata、strb;
输入就绪、rdata、slv_错误;
结束计时:master_cb
时钟从机(posedge时钟);
默认输入#1ns输出#1ns;
输入地址、保护、选择、启用、写入、wdata、strb;
输出就绪、rdata、slv_err;
结束计时:从机\u cb
时钟监视器(posedge时钟);
默认输入#1ns输出#1ns;
输入地址、保护、选择、启用、写入、wdata、strb、就绪、rdata、slv_err;
结束计时:监视器\u cb
modport master(输入时钟、复位、就绪、rdata、slv错误、输出地址、保护、选择、启用、写入、wdata、strb);
modport从机mp(输入时钟、复位、地址、保护、选择、启用、写入、wdata、strb、输出就绪、rdata、slv错误);
modport主控器同步器mp(时钟主控器cb);
modport从站同步(时钟从站cb);
endinterface:apb_if
成套apb_包装;
进口uvm_包装::*;
类apb_配置扩展了uvm_对象;
`uvm_对象_utils(apb_配置)
新函数(字符串名称=”);
超级新(名称);
端功能:新
endclass:apb_配置
分类apb顺序项目(地址宽度=3)
,选择宽度=2
,写入宽度=32
,读取宽度=写入宽度
)扩展uvm_序列_项;
localparam STRB_WIDTH=写入宽度%8?(写入宽度/8)+1:写入宽度/8;
`uvm对象实用程序(apb顺序项目)
//控制信息
随机位[31:0]地址;
随机位[2:0]保护;
随机位[SEL_WIDTH-1:0]SEL;
随机位写入;
兰德比特就绪;
//有效载荷信息
随机位[WRITE_WIDTH-1:0]wdata;
随机位[STRB_WIDTH-1:0]STRB;
//分析信息
随机位[READ_WIDTH-1:0]rdata;
兰德比特slv_错误;
约束读取构造{
写入==0->strb==0;
}
新函数(string name=“apb_seq_item”);
超级新(名称);
端功能:新
虚拟函数void do_copy(uvm_对象rhs);
apb顺序项目rhs;
如果(!$cast(rhs,rhs))开始
uvm_报告_错误(“do_复制:”,“强制转换失败”);
返回;
结束
超级。复制(右);//将副本链接到父类
地址=rhs_uu.addr;
防护装置=右侧防护装置;
sel=rhs_u2;.sel;
write=rhs_u2;write;
就绪=rhs_u2;就绪;
wdata=rhs_uuu.wdata;
strb=rhs_.strb;
rdata=rhs_uu.rdata;
slv_err=rhs_.slv_err;
endfunction:复制吗
虚拟功能位进行比较(uvm_对象rhs、uvm_比较器);
apb顺序项目rhs;
//如果强制转换失败,比较也会失败
//不需要检查null,因为这是在compare()中完成的
//调用do_compare()的函数
如果(!$cast(rhs,rhs))开始
返回0;
结束
返回(super.do_compare(rhs,comparer)&&
(地址=右侧地址)&&
(保护=右侧保护)&&
(sel=rhs_uu.sel)&&
(write=rhs_u2;write)&&
(准备就绪=右侧准备就绪)&&
(wdata=rhs_uUdata)&&
(strb=rhs_uu.strb)&&
(rdata=rhs_uu.rdata)&&
(slv_err=rhs_.slv_err));
endfunction:do_比较
虚拟函数字符串convert2string();
字符串s;
s=super.convert2string();
//请注意使用\t(制表符)和\n(换行符)来格式化列中的数据
//枚举的op_代码类型.name()方法返回与其值对应的字符串
s={s$psprintf(“\naddr\t\t:%0h”,addr)};
s={s,$psprintf(“\nprot\t\t:%0b”,prot)};
s={s,$psprintf(“\nsel\t\t:%0b”,sel)};
s={s$psprintf(“\nwrite\t\t:%0b”,write)};
s={s$psprintf(“\nready\t\t:%0b”,就绪)};
s={s$psprintf(“\nwdata\t\t:%0h”,wdata)};
s