diff --git a/tb/agents/dcache_if/dcache_if_driver.svh b/tb/agents/dcache_if/dcache_if_driver.svh index 10f63fdd2..91fdd372e 100644 --- a/tb/agents/dcache_if/dcache_if_driver.svh +++ b/tb/agents/dcache_if/dcache_if_driver.svh @@ -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); diff --git a/tb/agents/dcache_if/dcache_if_monitor.svh b/tb/agents/dcache_if/dcache_if_monitor.svh index a10ed659c..84ac2ba04 100644 --- a/tb/agents/dcache_if/dcache_if_monitor.svh +++ b/tb/agents/dcache_if/dcache_if_monitor.svh @@ -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 diff --git a/tb/env/mem_arbiter/mem_arbiter_scoreboard.svh b/tb/env/mem_arbiter/mem_arbiter_scoreboard.svh index 75039b2e3..03116a1ac 100755 --- a/tb/env/mem_arbiter/mem_arbiter_scoreboard.svh +++ b/tb/env/mem_arbiter/mem_arbiter_scoreboard.svh @@ -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