MCDF实验-lab2

实验2主要让我们逐渐从使用硬件盒子验证过渡到软件盒子(class) 来验证设计,理解类的继承和层次包含关系。

接口的使用

修改lab1的代码,使用接口来连接验证组件和DUT,所以验证组件chnl_initiator的端口变得非常“干净”,即chnl_intf intf。在使用接口之前需要定义接口chnl_intf和内部的接口,同时也要声明一个时钟块,它的功能是为了消除可能存在的竞争问题,确保时钟驱动数据之间有一定的延迟,以便于DUT顺利采样。

引入接口后的代码,例化的实例包括了只产生数据channel generator,只负责发送数据channel initiator以及作为验证组件和DUT之间的接口chnl_intf

实验要求:

  • channel_initiator发送的数据例如validdata与时钟clk均在同一个变化沿,没有任何延迟。这种0延迟的数据发送不利于波形的查看,要在之前的代码基础上使用intf.ck的方式来做数据驱动,并且再观察波形,查看驱动的数据与时钟上升沿的延迟。
  • 为了更好地控制相邻数据之间的空闲间隔,引入了一个变量idle_cycles,它表示相邻有效数据之间的间隔。之前的代码会使得有效数据之间保持固定的一个空闲周期,需要使用idle_cycles来灵活控制有效数据之间的空闲周期。
1
interface chnl_intf(input clk, input rstn);
2
  logic [31:0] ch_data;
3
  logic        ch_valid;
4
  logic        ch_ready;
5
  logic [5:0] ch_margin;
6
  clocking drv_ck @(posedge clk);
7
    default input #1ns output #1ns;
8
    output ch_data, ch_valid;
9
    input ch_ready, ch_margin;
10
  endclocking
11
endinterface
12
13
module chnl_initiator(chnl_intf intf);
14
  string name;
15
  int idle_cycles = 1;
16
  function automatic void set_idle_cycles(int n);
17
    idle_cycles = n;
18
  endfunction
19
  function automatic void set_name(string s);
20
    name = s;
21
  endfunction
22
  task automatic chnl_write(input logic[31:0] data);
23
    @(posedge intf.clk);
24
    // USER TODO 1.1
25
    // Please use the clocking drv_ck of chnl_intf to drive data
26
    intf.drv_ck.ch_valid <= 1;
27
    intf.drv_ck.ch_data <= data;
28
    wait(intf.ch_ready === 'b1);
29
    $display("%t channel initiator [%s] sent data %x", $time, name, data);
30
    // USER TODO 1.2
31
    // Apply variable idle_cycles and decide how many idle cycles to be
32
    // inserted between two sequential data
33
    repeat(idle_cycles) chnl_idle();
34
  endtask
35
  task automatic chnl_idle();
36
    @(posedge intf.clk);
37
    // USER TODO 1.1
38
    // Please use the clocking drv_ck of chnl_intf to drive data
39
    intf.drv_ck.ch_valid <= 0;
40
    intf.drv_ck.ch_data <= 0;
41
  endtask
42
endmodule

仿真的结束

在tb module,利用fork-join语句来实现三个chnl_initiator同时发送数据的要求。同时将不同的test也组装到task中,以此来区分不同的测试内容,这是由于每一个测试任务的测试目的和要求都不相同。

实验要求:

  • 参考basic_test(), 实现burst_test()方法,使得每个chnl_initiatoridle_cycles设置为0,同时发送500个数据,最后结束测试。
  • 实现fifo_full_test()方法,使得无论采取什么数值的idle_cycles,也无论发送多少个数据,只要各个chnl_initiator的不停发送使得对应的channel缓存变为满标志(ready拉低),那么可以在三个channel都拉低ready时(不必要同时拉低,可以先后拉低即可),便可以立即结束测试
1
// each channel send data with idle_cycles inside [1:3]
2
// each channel send out 200 data
3
// then to finish the test
4
task automatic basic_test();
5
    // verification component initializationi
6
    chnl0_gen.initialize(0);
7
    chnl1_gen.initialize(1);
8
    chnl2_gen.initialize(2);
9
    chnl0_init.set_name("chnl0_init");
10
    chnl1_init.set_name("chnl1_init");
11
    chnl2_init.set_name("chnl2_init");
12
    chnl0_init.set_idle_cycles($urandom_range(1, 3));
13
    chnl1_init.set_idle_cycles($urandom_range(1, 3));
14
    chnl2_init.set_idle_cycles($urandom_range(1, 3));
15
    $display("basic_test initialized components");
16
    wait (rstn === 1'b1);
17
    repeat(5) @(posedge clk);
18
    $display("basic_test started testing DUT");
19
    // Please check the SV book for fork-join basic knowledge
20
    // and get understood it is for parallel thread running
21
    fork
22
        repeat(100) chnl0_init.chnl_write(chnl0_gen.get_data());
23
        repeat(100) chnl1_init.chnl_write(chnl1_gen.get_data());
24
        repeat(100) chnl2_init.chnl_write(chnl2_gen.get_data());
25
    join
26
    // waiting until transfering all of the data
27
    fork
28
        wait(chnl0_init.intf.ch_margin == 'h20);
29
        wait(chnl1_init.intf.ch_margin == 'h20);
30
        wait(chnl2_init.intf.ch_margin == 'h20);
31
    join
32
    $display("basic_test finished testing DUT");
33
endtask
34
35
// USER TODO 2.1
36
// each channel send data with idle_cycles == 0
37
// each channel send out 500 data
38
// then to finish the test
39
task automatic burst_test();
40
    // initiator
41
    chnl0_init.set_name("chnl0_init");
42
    chnl1_init.set_name("chnl1_init");
43
    chnl2_init.set_name("chnl2_init");
44
45
    chnl0_init.set_idle_cycles(0);
46
    chnl1_init.set_idle_cycles(0);
47
    chnl2_init.set_idle_cycles(0);
48
    // generator
49
    chnl0_gen.initialize(0);
50
    chnl1_gen.initialize(1);
51
    chnl2_gen.initialize(2);
52
    $display("burst_test initialized components");
53
    wait (rstn === 1'b1);
54
    repeat(5) @(posedge clk);
55
    $display("burst_test started testing DUT");
56
    fork
57
        begin
58
            repeat(500) chnl0_init.chnl_write(chnl0_gen.get_data());
59
            chnl0_init.chnl_idle();
60
        end
61
        begin
62
            repeat(500) chnl1_init.chnl_write(chnl1_gen.get_data());
63
            chnl1_init.chnl_idle();
64
        end
65
        begin
66
            repeat(500) chnl2_init.chnl_write(chnl2_gen.get_data());
67
            chnl2_init.chnl_idle();
68
        end
69
    join
70
    
71
    fork
72
      wait(chnl0_init.intf.ch_margin == 'h20);
73
      wait(chnl1_init.intf.ch_margin == 'h20);
74
      wait(chnl2_init.intf.ch_margin == 'h20);
75
    join
76
    $display("burst_test finished testung DUT");
77
78
endtask
79
80
// USER TODO 2.2
81
// The test should be immediately finished when all of channels
82
// have been reached fifo full state, but not all reaching
83
// fifo full at the same time
84
task automatic fifo_full_test();
85
    // initiator
86
    chnl0_init.set_name("chnl0_init");
87
    chnl1_init.set_name("chnl1_init");
88
    chnl2_init.set_name("chnl2_init");
89
90
    chnl0_init.set_idle_cycles(0);
91
    chnl1_init.set_idle_cycles(0);
92
    chnl2_init.set_idle_cycles(0);
93
    // generator
94
    chnl0_gen.initialize(0);
95
    chnl1_gen.initialize(1);
96
    chnl2_gen.initialize(2);
97
    $display("burst_test initialized components");
98
    wait (rstn === 1'b1);
99
    repeat(5) @(posedge clk);
100
    $display("fifo_full_test started testing DUT");
101
    // fork join_none,执行内部语句时,父线程继续执行
102
    fork
103
        forever chnl0_init.chnl_write(chnl0_gen.get_data());
104
        forever chnl1_init.chnl_write(chnl1_gen.get_data());
105
        forever chnl2_init.chnl_write(chnl2_gen.get_data());
106
    join_none
107
    // 分别三个都满足,并非同时
108
    fork
109
        wait(chnl0_init.intf.ch_margin == 0);
110
        wait(chnl1_init.intf.ch_margin == 0);
111
        wait(chnl2_init.intf.ch_margin == 0);
112
    join    
113
    $display("fifo_full_test finished testing DUT");
114
    
115
    $display("fifo_full_test: set and ensure all agents' initiator are idle state");
116
    fork
117
        chnl0_init.chnl_idle();
118
        chnl1_init.chnl_idle();
119
        chnl2_init.chnl_idle();
120
    join
121
122
    $display("fifo_full_test waiting DUT transfering all of data");
123
    fork
124
        wait(chnl0_init.intf.ch_margin == 'h20);
125
        wait(chnl1_init.intf.ch_margin == 'h20);
126
        wait(chnl2_init.intf.ch_margin == 'h20);
127
    join
128
    $display("fifo_full_test: 3 channel fifos have transferred all data");
129
130
    $display("fifo_full_test finished testing DUT");
131
endtask

fork join_none在执行内部语句时父线程继续执行,fork join 只要内部语句分别都满足,并非同时满足,就可跳出

类的例化和类的成员

将之前用来封装验证功能的硬件盒子(module)中的数据和内容移植到软件盒子(class)中来。掌握类的基本例化,类的成员变量访问权限以及类的成员方法如何定义和使用。

实验要求:

  • 将module的chnl_initiatorchnl_generator改成class的chnl_initiatorchnl_generator,同时定义一个用来封装发送数据的类chnl_trans
  • 由于每一个chnl_initiator都需要使用接口chnl_intf来发送数据,在发送数据之前需要确保
    chnl_initiator中的接口不是悬空的,即需要由外部被传递。通过调用chnl_initiator的方法来完成接口的传递。
  • 注意class里面声明接口的指针必须要加上virtual关键字。
1
class chnl_trans;
2
  int data;
3
  int id;
4
  int num;
5
endclass
6
7
class chnl_initiator;
8
  local string name;
9
  local int idle_cycles;
10
  virtual chnl_intf intf;
11
12
  function new(string name = "chnl_initiator");
13
    this.name = name;
14
    this.idle_cycles = 1;
15
  endfunction
16
17
  function void set_idle_cycles(int n);
18
    this.idle_cycles = n;
19
  endfunction
20
21
  function void set_name(string s);
22
    this.name = s;
23
  endfunction
24
25
  function void set_interface(virtual chnl_intf intf);
26
    if(intf == null)
27
      $error("interface handle is NULL, please check if target interface has been intantiated");
28
    else
29
      this.intf = intf;
30
  endfunction
31
32
    task chnl_write(input chnl_trans t);
33
      @(posedge intf.clk);
34
      // USER TODO 1.1
35
      // Please use the clocking drv_ck of chnl_intf to drive data
36
      intf.drv_ck.ch_valid <= 1;
37
      intf.drv_ck.ch_data <= t.data;
38
	  
39
      @(negedge intf.clk);
40
      wait(intf.ch_ready === 'b1);
41
      $display("%t channel initiator [%s] sent data %x", $time, name, t.data);
42
      // USER TODO 1.2
43
      // Apply variable idle_cycles and decide how many idle cycles to be
44
      // inserted between two sequential data
45
      repeat(this.idle_cycles) chnl_idle();
46
    endtask
47
    
48
    task chnl_idle();
49
      @(posedge intf.clk);
50
      // USER TODO 1.1
51
      // Please use the clocking drv_ck of chnl_intf to drive data
52
      intf.drv_ck.ch_valid <= 0;
53
      intf.drv_ck.ch_data <= 0;
54
    endtask
55
endclass
56
57
// USER TODO 3.4
58
// check if the object use is correct?
59
class chnl_generator;
60
  chnl_trans trans[$];
61
  int num;
62
  int id;
63
  chnl_trans t;
64
  function new(int n);
65
    this.id = n;
66
    this.num = 0;
67
    //t = new();
68
  endfunction
69
  function chnl_trans get_trans();
70
    t = new();
71
    t.data = 'h00C0_0000 + (this.id<<16) + this.num;
72
    t.id = this.id;
73
    t.num = this.num;
74
    this.num++;
75
    this.trans.push_back(t);
76
    return t;
77
  endfunction
78
endclass
79
// module tb
80
module tb3;
81
  logic         clk;
82
  logic         rstn;
83
  logic [31:0]  mcdt_data;
84
  logic         mcdt_val;
85
  logic [ 1:0]  mcdt_id;
86
  
87
  mcdt dut(
88
     .clk_i       (clk                )
89
    ,.rstn_i      (rstn               )
90
    ,.ch0_data_i  (chnl0_if.ch_data   )
91
    ,.ch0_valid_i (chnl0_if.ch_valid  )
92
    ,.ch0_ready_o (chnl0_if.ch_ready  )
93
    ,.ch0_margin_o(chnl0_if.ch_margin )
94
    ,.ch1_data_i  (chnl1_if.ch_data   )
95
    ,.ch1_valid_i (chnl1_if.ch_valid  )
96
    ,.ch1_ready_o (chnl1_if.ch_ready  )
97
    ,.ch1_margin_o(chnl1_if.ch_margin )
98
    ,.ch2_data_i  (chnl2_if.ch_data   )
99
    ,.ch2_valid_i (chnl2_if.ch_valid  )
100
    ,.ch2_ready_o (chnl2_if.ch_ready  )
101
    ,.ch2_margin_o(chnl2_if.ch_margin )
102
    ,.mcdt_data_o (mcdt_data          )
103
    ,.mcdt_val_o  (mcdt_val           )
104
    ,.mcdt_id_o   (mcdt_id            )
105
  );
106
  // clock generation
107
  initial begin 
108
    clk <= 0;
109
    forever begin
110
      #5 clk <= !clk;
111
    end
112
  end
113
  
114
  // reset trigger
115
  initial begin 
116
    #10 rstn <= 0;
117
    repeat(10) @(posedge clk);
118
    rstn <= 1;
119
  end
120
121
  chnl_intf chnl0_if(.*);
122
  chnl_intf chnl1_if(.*);
123
  chnl_intf chnl2_if(.*);
124
125
  chnl_initiator chnl0_init;
126
  chnl_initiator chnl1_init;
127
  chnl_initiator chnl2_init;
128
  chnl_generator chnl0_gen;
129
  chnl_generator chnl1_gen;
130
  chnl_generator chnl2_gen;
131
  
132
  initial begin 
133
    // USER TODO 3.1
134
    // instantiate the components chn0/1/2_init chnl0/1/2_gen
135
    chnl0_init = new("chnl0_init");
136
    chnl1_init = new("chnl1_init");
137
    chnl2_init = new("chnl2_init");
138
139
    chnl0_gen = new(0);
140
    chnl1_gen = new(1);
141
    chnl2_gen = new(2);
142
143
144
    // USER TODO 3.2
145
    // assign the interface handle to each chnl_initiator objects
146
    chnl0_init.set_interface(chnl0_if); 
147
    chnl1_init.set_interface(chnl1_if);
148
    chnl2_init.set_interface(chnl2_if);
149
    // USER TODO 3.3
150
    // START TESTs
151
    basic_test();
152
    burst_test();
153
    fifo_full_test();
154
155
      $display("*****************all of tests have been finished********************");
156
    $finish();
157
  end
158
endmodule

包的定义和类的继承

进一步引入新的类chnl_agentchnl_root_testchnl_basic_testchnl_burst_testchnl_fifo_full_test,同时将所有的类(都是与channel相关的验证组件类)封装到专门包裹软件类的容器package chnl_pkg中且完成编译。编译后的chnl_pkg会被默认编译到work中,与其它的module是一同并列放置的。

  • chnl_agent:将它作为一个标准组件单元,包括generator、driver(initiator)和monitor。所以chnl_initiatorchnl_generator应该放在agent中例化
  • task实现的测试任务由类来实现:父类chnl_root_test,子类chnl_basic_testchnl_burst_testchnl_fifo_full_test

实验要求:

  • 将各个类封装到 package chnl_pkg 中,然后需要从 chnl_pkg 中引入其中的类,并在module tb4 中声明类的句柄
  • 实现类chnl_burst_testchnl_fifo_full_test
  • 例化已经声明过的三个组件
  • 完成从test一层的接口传递任务,使得其内部各个组件都可以得到需要的接口
1
`timescale 1ns/1ps
2
3
interface chnl_intf(input clk, input rstn);
4
  logic [31:0] ch_data;
5
  logic        ch_valid;
6
  logic        ch_ready;
7
  logic [ 5:0] ch_margin;
8
  clocking drv_ck @(posedge clk);
9
    default input #1ns output #1ns;
10
    output ch_data, ch_valid;
11
    input ch_ready, ch_margin;
12
  endclocking
13
endinterface
14
15
package chnl_pkg;
16
  class chnl_trans;
17
    int data;
18
    int id;
19
    int num;
20
  endclass: chnl_trans
21
  
22
  class chnl_initiator;
23
    local string name;
24
    local int idle_cycles;
25
    local virtual chnl_intf intf;
26
  
27
    function new(string name = "chnl_initiator");
28
      this.name = name;
29
      this.idle_cycles = 1;
30
    endfunction
31
  
32
    function void set_idle_cycles(int n);
33
      this.idle_cycles = n;
34
    endfunction
35
  
36
    function void set_name(string s);
37
      this.name = s;
38
    endfunction
39
  
40
    function void set_interface(virtual chnl_intf intf);
41
      if(intf == null)
42
        $error("interface handle is NULL, please check if target interface has been intantiated");
43
      else
44
        this.intf = intf;
45
    endfunction
46
  
47
    task chnl_write(input chnl_trans t);
48
      @(posedge intf.clk);
49
      // USER TODO 1.1
50
      // Please use the clocking drv_ck of chnl_intf to drive data
51
      intf.drv_ck.ch_valid <= 1;
52
      intf.drv_ck.ch_data <= t.data;
53
	      @(negedge intf.clk);
54
      wait(intf.ch_ready === 'b1);
55
      $display("%t channel initiator [%s] sent data %x", $time, name, t.data);
56
      // USER TODO 1.2
57
      // Apply variable idle_cycles and decide how many idle cycles to be
58
      // inserted between two sequential data
59
      repeat(this.idle_cycles) chnl_idle();
60
    endtask
61
    
62
    task chnl_idle();
63
      @(posedge intf.clk);
64
      // USER TODO 1.1
65
      // Please use the clocking drv_ck of chnl_intf to drive data
66
      intf.drv_ck.ch_valid <= 0;
67
      intf.drv_ck.ch_data <= 0;
68
    endtask
69
  endclass: chnl_initiator
70
  
71
  class chnl_generator;
72
    chnl_trans trans[$];
73
    int num;
74
    int id;
75
    function new(int n);
76
      this.id = n;
77
      this.num = 0;
78
    endfunction
79
    function chnl_trans get_trans();
80
      chnl_trans t = new();
81
      t.data = 'h00C0_0000 + (this.id<<16) + this.num;
82
      t.id = this.id;
83
      t.num = this.num;
84
      this.num++;
85
      this.trans.push_back(t);
86
      return t;
87
    endfunction
88
  endclass: chnl_generator
89
90
  class chnl_agent;
91
    chnl_generator gen;
92
    chnl_initiator init;
93
    local int ntrans;
94
    virtual chnl_intf vif;
95
    function new(string name = "chnl_agent", int id = 0, int ntrans = 1);
96
      this.gen = new(id);
97
      this.init = new(name);
98
      this.ntrans = ntrans;
99
    endfunction
100
    function void set_ntrans(int n);
101
      this.ntrans = n;
102
    endfunction
103
    function void set_interface(virtual chnl_intf vif);
104
      this.vif = vif;
105
      init.set_interface(vif);
106
    endfunction
107
    task run();
108
      repeat(this.ntrans) this.init.chnl_write(this.gen.get_trans());
109
      this.init.chnl_idle(); // set idle after all data sent out
110
    endtask
111
  endclass: chnl_agent
112
113
  class chnl_root_test;
114
    chnl_agent agent[3];
115
    protected string name;
116
    function new(int ntrans = 100, string name = "chnl_root_test");
117
      foreach(agent[i]) begin
118
        this.agent[i] = new($sformatf("chnl_agent%0d",i), i, ntrans);
119
      end
120
      this.name = name;
121
      $display("%s instantiate objects", this.name);
122
    endfunction
123
    task run();
124
      $display("%s started testing DUT", this.name);
125
      fork
126
        agent[0].run();
127
        agent[1].run();
128
        agent[2].run();
129
      join
130
      $display("%s waiting DUT transfering all of data", this.name);
131
      fork
132
        wait(agent[0].vif.ch_margin == 'h20);
133
        wait(agent[1].vif.ch_margin == 'h20);
134
        wait(agent[2].vif.ch_margin == 'h20);
135
      join
136
      $display("%s: 3 channel fifos have transferred all data", this.name);
137
      $display("%s finished testing DUT", this.name);
138
    endtask
139
    function void set_interface(virtual chnl_intf ch0_vif, virtual chnl_intf ch1_vif, virtual chnl_intf ch2_vif);
140
      agent[0].set_interface(ch0_vif);
141
      agent[1].set_interface(ch1_vif);
142
      agent[2].set_interface(ch2_vif);
143
    endfunction
144
  endclass
145
  // each channel send data with idle_cycles inside [1:3]
146
  // each channel send out 200 data
147
  // then to finish the test
148
  class chnl_basic_test extends chnl_root_test;
149
    function new(int ntrans = 200, string name = "chnl_basic_test");
150
      super.new(ntrans, name);
151
      foreach(agent[i]) begin
152
        this.agent[i].init.set_idle_cycles($urandom_range(1, 3));
153
      end
154
      $display("%s configured objects", this.name);
155
    endfunction
156
  endclass: chnl_basic_test
157
  // USER TODO 4.2
158
  // Refer to chnl_basic_test, and extend another 2 tests
159
  // chnl_burst_test, chnl_fifo_full_test
160
  // each channel send data with idle_cycles == 0
161
  // each channel send out 500 data
162
  // then to finish the test
163
  class chnl_burst_test extends chnl_root_test;
164
    //USER TODO
165
    function new(int ntrans = 500, string name = "chnl_burst_test");
166
      super.new(ntrans, name);
167
      foreach(agent[i]) begin
168
        this.agent[i].init.set_idle_cycles(0);
169
      end
170
      $display("%s configured objects", this.name);
171
    endfunction
172
  endclass: chnl_burst_test
173
  // USER TODO 4.2
174
  // The test should be immediately finished when all of channels
175
  // have been reached fifo full state, but not all reaching
176
  // fifo full at the same time
177
  class chnl_fifo_full_test extends chnl_root_test;
178
    // USER TODO
179
    function new(int ntrans = 1_000_000, string name = "chnl_fifo_full_test");
180
      super.new(ntrans, name);
181
      foreach(agent[i]) begin
182
        this.agent[i].init.set_idle_cycles(0);
183
      end
184
      $display("%s configured objects", this.name);
185
    endfunction
186
    task run();
187
      $display("%s started testing DUT", this.name);
188
      fork: fork_all_run
189
        agent[0].run();
190
        agent[1].run();
191
        agent[2].run();
192
      join_none
193
      $display("%s: 3 agents running now", this.name);
194
195
      $display("%s: waiting 3 channel fifos to be full", this.name);
196
      fork
197
        wait(agent[0].vif.ch_margin == 0);
198
        wait(agent[1].vif.ch_margin == 0);
199
        wait(agent[2].vif.ch_margin == 0);
200
      join
201
      $display("%s: 3 channel fifos have reached full", this.name);
202
203
      $display("%s: stop 3 agents running", this.name);
204
      disable fork_all_run;
205
      $display("%s: set and ensure all agents' initiator are idle state", this.name);
206
      fork
207
        agent[0].init.chnl_idle();
208
        agent[1].init.chnl_idle();
209
        agent[2].init.chnl_idle();
210
      join
211
212
      $display("%s waiting DUT transfering all of data", this.name);
213
      fork
214
        wait(agent[0].vif.ch_margin == 'h20);
215
        wait(agent[1].vif.ch_margin == 'h20);
216
        wait(agent[2].vif.ch_margin == 'h20);
217
      join
218
      $display("%s: 3 channel fifos have transferred all data", this.name);
219
220
      $display("%s finished testing DUT", this.name);
221
    endtask
222
  endclass: chnl_fifo_full_test
223
224
endpackage: chnl_pkg
225
226
module tb4_ref;
227
  logic         clk;
228
  logic         rstn;
229
  logic [31:0]  mcdt_data;
230
  logic         mcdt_val;
231
  logic [ 1:0]  mcdt_id;
232
  
233
  mcdt dut(
234
     .clk_i       (clk                )
235
    ,.rstn_i      (rstn               )
236
    ,.ch0_data_i  (chnl0_if.ch_data   )
237
    ,.ch0_valid_i (chnl0_if.ch_valid  )
238
    ,.ch0_ready_o (chnl0_if.ch_ready  )
239
    ,.ch0_margin_o(chnl0_if.ch_margin )
240
    ,.ch1_data_i  (chnl1_if.ch_data   )
241
    ,.ch1_valid_i (chnl1_if.ch_valid  )
242
    ,.ch1_ready_o (chnl1_if.ch_ready  )
243
    ,.ch1_margin_o(chnl1_if.ch_margin )
244
    ,.ch2_data_i  (chnl2_if.ch_data   )
245
    ,.ch2_valid_i (chnl2_if.ch_valid  )
246
    ,.ch2_ready_o (chnl2_if.ch_ready  )
247
    ,.ch2_margin_o(chnl2_if.ch_margin )
248
    ,.mcdt_data_o (mcdt_data          )
249
    ,.mcdt_val_o  (mcdt_val           )
250
    ,.mcdt_id_o   (mcdt_id            )
251
  );
252
  // clock generation
253
  initial begin 
254
    clk <= 0;
255
    forever begin
256
      #5 clk <= !clk;
257
    end
258
  end
259
  // reset trigger
260
  initial begin 
261
    #10 rstn <= 0;
262
    repeat(10) @(posedge clk);
263
    rstn <= 1;
264
  end
265
  // USER TODO 4.1
266
  // import defined class from chnl_pkg
267
  import chnl_pkg::*;
268
269
  chnl_intf chnl0_if(.*);
270
  chnl_intf chnl1_if(.*);
271
  chnl_intf chnl2_if(.*);
272
273
  chnl_basic_test basic_test;
274
  chnl_burst_test burst_test;
275
  chnl_fifo_full_test fifo_full_test;
276
277
  initial begin 
278
    basic_test = new();
279
    burst_test = new();
280
    fifo_full_test = new();
281
    // USER TODO 4.4
282
    // assign the interface handle to each chnl_initiator objects
283
    basic_test.set_interface(chnl0_if, chnl1_if, chnl2_if);
284
    burst_test.set_interface(chnl0_if, chnl1_if, chnl2_if);
285
    fifo_full_test.set_interface(chnl0_if, chnl1_if, chnl2_if);
286
    // USER TODO 4.5
287
    // START TESTs
288
    basic_test.run(); 
289
    burst_test.run();
290
    fifo_full_test.run();
291
      $display("*****************all of tests have been finished********************");
292
    $finish();
293
  end
294
endmodule

验证环境结构

结构

软件和硬件通过接口连接,所有的类封装到chnl_pkg 中并编译到work库中。

  • 接口传递 interface 的指针如何传递到 initiator?

    通过chnl_root_testset_interface() function, 然后又调用agentset_interface()将值传入initiator。

  • 仿真是怎样运行的?

    通过test的run()让每个agent的run()运行起来,然后再让各个generator和initiator运行起来。