Implement monitor of dcache interface, test passing

This commit is contained in:
Florian Zaruba 2017-05-29 18:15:52 +02:00
parent c1269588c4
commit b2ad6f058e
3 changed files with 84 additions and 25 deletions

View file

@ -73,16 +73,17 @@ class dcache_if_driver extends uvm_driver #(dcache_if_seq_item);
if (m_vif.pck.data_gnt && m_vif.mck.data_req) begin
// push the low portion of the address a.k.a. the index
address_index.push_back(m_vif.mck.address_index);
lock.get(1);
// wait a couple of cycles, but at least one
@(m_vif.mck);
// in this cycle the tag is ready
address_tag.push_back(m_vif.mck.address_tag);
lock.get(1);
// randomize rvalid here
repeat ($urandom_range(0,2)) @(m_vif.mck);
repeat ($urandom_range(1,2)) @(m_vif.mck);
m_vif.mck.data_rvalid <= 1'b1;
// compose the address
address_out = {address_tag.pop_front(), address_index.pop_front()};
m_vif.mck.data_rdata <= address_out;
// put back the lock
lock.put(1);
end else
@ -114,30 +115,30 @@ class dcache_if_driver extends uvm_driver #(dcache_if_seq_item);
m_vif.sck.data_wdata <= 64'b0;
// request read or write
// we don't care about results at this point
forever begin
seq_item_port.get_next_item(cmd);
// do begin
m_vif.sck.data_req <= 1'b1;
m_vif.sck.address_index <= cmd.address[11:0];
m_vif.sck.data_be <= cmd.be;
m_vif.sck.data_we <= (cmd.mode == READ) ? 1'b0 : 1'b1;
m_vif.sck.data_wdata <= cmd.data;
fork
forever begin
seq_item_port.get_next_item(cmd);
// do begin
m_vif.sck.data_req <= 1'b1;
m_vif.sck.address_index <= cmd.address[11:0];
m_vif.sck.data_be <= cmd.be;
m_vif.sck.data_we <= (cmd.mode == READ) ? 1'b0 : 1'b1;
m_vif.sck.data_wdata <= cmd.data;
@(m_vif.sck iff m_vif.sck.data_gnt);
m_vif.sck.address_tag <= cmd.address[43:12];
m_vif.sck.tag_valid <= 1'b1;
m_vif.sck.data_req <= 1'b0;
@(m_vif.sck iff m_vif.sck.data_gnt);
m_vif.sck.address_tag <= cmd.address[43:12];
m_vif.sck.data_req <= 1'b0;
// delay the next request
repeat (cmd.requestDelay) @(m_vif.sck);
// delay the next request
// if there is delay, wait one clock cycle and set the tag valid back to zero
if (cmd.requestDelay != 0) begin
@(m_vif.sck);
m_vif.sck.tag_valid <= 1'b0;
seq_item_port.item_done();
end
repeat (cmd.requestDelay-1) @(m_vif.sck);
seq_item_port.item_done();
end
forever begin
@(m_vif.sck);
m_vif.sck.tag_valid <= m_vif.sck.data_gnt;
end
join_none
end
seq_item_port.get_next_item(cmd);

View file

@ -26,6 +26,9 @@ class dcache_if_monitor extends uvm_component;
// Virtual Interface
virtual dcache_if m_vif;
mailbox address_mbx;
mailbox data_mbx;
//---------------------
// Data Members
//---------------------
@ -41,6 +44,8 @@ class dcache_if_monitor extends uvm_component;
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration dcache_if_agent_config from uvm_config_db. Have you set() it?")
m_ap = new("m_ap", this);
address_mbx = new();
data_mbx = new();
endfunction: build_phase
@ -51,12 +56,63 @@ class dcache_if_monitor extends uvm_component;
task run_phase(uvm_phase phase);
string if_type = this.get_full_name();//(m_cfg.dcache_if_config inside {SLAVE, SLAVE_REPLAY, SLAVE_NO_RANDOM}) ? "[SLAVE]" : "[MASTER]";
logic [11:0] address_index [$];
logic [44:0] address;
logic[7:0] be [$];
dcache_if_seq_item cmd = dcache_if_seq_item::type_id::create("cmd");
dcache_if_seq_item cloned_item;
// Monitor process
fork
// 1. Thread
// detect a request
req: begin
forever begin
@(m_vif.pck iff (m_vif.pck.data_gnt && m_vif.pck.data_req));
// save tag and byte enable
// $display("%s: %t, Putting index: %0h", if_type, $time(), m_vif.pck.address_index);
address_index.push_back(m_vif.pck.address_index);
be.push_back(m_vif.pck.data_be);
end
end
// 2. Thread
// detect a valid tag and save it
tag_valid: begin
forever begin
@(m_vif.pck iff m_vif.pck.tag_valid);
// save tag for later use
address_mbx.put({m_vif.pck.address_tag, address_index.pop_front()});
// $display("%s: %t, Putting Tag %0h, Queue Size: %d", if_type, $time(), m_vif.pck.address_tag, address_mbx.num());
end
end
// 3. thread wait for valid data
read_valid: begin
forever begin
@(m_vif.pck iff m_vif.pck.data_rvalid);
data_mbx.put(m_vif.pck.data_rdata);
end
end
respsonese_gen: begin
forever begin
dcache_if_seq_item cloned_item;
// blocking get, wait for both to be ready
data_mbx.get(cmd.data);
address_mbx.get(cmd.address);
cmd.be = be.pop_front();
// $display("%s: %t, Popping %0h from MBX", if_type, $time(), cmd.address);
// was this from a master or slave agent monitor?
cmd.isSlaveAnswer = (m_cfg.dcache_if_config inside {SLAVE, SLAVE_REPLAY, SLAVE_NO_RANDOM}) ? 1'b1 : 1'b0;
$cast(cloned_item, cmd.clone());
m_ap.write(cloned_item);
end
end
join_any
$cast(cloned_item, cmd.clone());
m_ap.write(cloned_item);
endtask : run_phase
endclass : dcache_if_monitor

View file

@ -38,6 +38,8 @@ class mem_arbiter_scoreboard extends uvm_scoreboard;
if (~seq_item.isSlaveAnswer) begin
if (seq_item.address !== seq_item.data) begin
`uvm_error( "DCache Arbiter Scoreboard", $sformatf("Got: %0h Expected: %0h", seq_item.address, seq_item.data) )
end else begin
// `uvm_info( "DCache Arbiter Scoreboard", $sformatf("Got: %0h Expected: %0h", seq_item.address, seq_item.data), UVM_LOW)
end
master_answer_cnt++;
end else begin