Remove tb folder as it moved to seperate repo

This commit is contained in:
Florian Zaruba 2017-07-06 15:06:20 +02:00
parent 70e16022a9
commit 8bee980c7e
148 changed files with 0 additions and 8559 deletions

View file

@ -1,49 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 8.5.2017
// Description: Core Interface
//
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
`ifndef CORE_IF_SV
`define CORE_IF_SV
interface core_if (
input clk
);
wire clock_en;
wire test_en;
wire fetch_enable;
wire core_busy;
wire [63:0] boot_addr;
wire [3:0] core_id;
wire [5:0] cluster_id;
wire irq;
wire [4:0] irq_id;
wire irq_ack;
wire irq_sec;
wire sec_lvl;
clocking mck @(posedge clk);
output clock_en, test_en, fetch_enable, boot_addr, core_id, cluster_id, irq, irq_id, irq_sec;
input core_busy, sec_lvl, irq_ack;
endclocking
clocking pck @(posedge clk);
input clock_en, test_en, fetch_enable, boot_addr, core_id, cluster_id, irq, irq_id, irq_sec, core_busy, sec_lvl, irq_ack;
endclocking
endinterface
`endif

View file

@ -1,57 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: Main agent object core_if. Builds and instantiates the appropriate
// subcomponents like the monitor, driver etc. all based on the
// agent configuration object.
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class core_if_agent extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(core_if_agent)
//------------------------------------------
// Data Members
//------------------------------------------
core_if_agent_config m_cfg;
//------------------------------------------
// Component Members
//------------------------------------------
uvm_analysis_port #(core_if_seq_item) ap;
core_if_driver m_driver;
core_if_monitor m_monitor;
core_if_sequencer m_sequencer;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "core_if_agent", uvm_component parent = null);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(core_if_agent_config)::get(this, "", "core_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration core_if_agent_config from uvm_config_db. Have you set() it?")
m_driver = core_if_driver::type_id::create("m_driver", this);
m_sequencer = core_if_sequencer::type_id::create("m_sequencer", this);
m_monitor = core_if_monitor::type_id::create("m_monitor", this);
endfunction : build_phase
function void connect_phase(uvm_phase phase);
m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
// m_monitor.ap.connect(m_cov_monitor.analysis_port)
m_driver.m_cfg = m_cfg;
m_monitor.m_cfg = m_cfg;
endfunction: connect_phase
endclass : core_if_agent

View file

@ -1,37 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: Agent configuration object core_if
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class core_if_agent_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(core_if_agent_config)
// Virtual Interface
virtual core_if m_vif;
//------------------------------------------
// Data Members
//------------------------------------------
// Is the agent active or passive
uvm_active_passive_enum active = UVM_ACTIVE;
// Standard UVM Methods:
function new(string name = "core_if_agent_config");
super.new(name);
endfunction : new
endclass : core_if_agent_config

View file

@ -1,37 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: core_if_agent package - compile unit
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
package core_if_agent_pkg;
// UVM Import
import uvm_pkg::*;
`include "uvm_macros.svh"
// Sequence item to model transactions
`include "core_if_seq_item.svh"
// Agent configuration object
`include "core_if_agent_config.svh"
// Driver
`include "core_if_driver.svh"
// Coverage monitor
// `include "core_if_coverage_monitor.svh"
// Monitor that includes analysis port
`include "core_if_monitor.svh"
// Sequencer
`include "core_if_sequencer.svh"
// Main agent
`include "core_if_agent.svh"
// Sequence
`include "core_if_sequence.svh"
endpackage: core_if_agent_pkg

View file

@ -1,60 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: Driver for interface core_if
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class core_if_driver extends uvm_driver #(core_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(core_if_driver)
// Virtual Interface
virtual core_if m_vif;
//---------------------
// Data Members
//---------------------
core_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "core_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
// core_if_seq_item cmd;
// seq_item_port.get_next_item(cmd);
// seq_item_port.item_done();
m_vif.mck.test_en <= 1'b0;
m_vif.mck.clock_en <= 1'b1;
m_vif.mck.boot_addr <= 64'h80000000;
m_vif.mck.core_id <= 4'b0;
m_vif.mck.cluster_id <= 6'b0;
m_vif.mck.irq <= 1'b0;
m_vif.mck.irq_id <= 5'b0;
m_vif.mck.irq_sec <= 1'b0;
m_vif.mck.fetch_enable <= 1'b0;
repeat (20) @(m_vif.mck);
m_vif.mck.fetch_enable <= 1'b1;
endtask : run_phase
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(core_if_agent_config)::get(this, "", "core_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration core_if_agent_config from uvm_config_db. Have you set() it?")
m_vif = m_cfg.m_vif;
endfunction: build_phase
endclass : core_if_driver

View file

@ -1,62 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: core_if Monitor, monitors the DUT's pins and writes out
// appropriate sequence items as defined for this particular dut
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class core_if_monitor extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(core_if_monitor)
// analysis port
uvm_analysis_port #(core_if_seq_item) m_ap;
// Virtual Interface
virtual core_if m_vif;
//---------------------
// Data Members
//---------------------
core_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "core_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(core_if_agent_config)::get(this, "", "core_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration core_if_agent_config from uvm_config_db. Have you set() it?")
m_ap = new("m_ap", this);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
// connect virtual interface
m_vif = m_cfg.m_vif;
endfunction
task run_phase(uvm_phase phase);
core_if_seq_item cmd = core_if_seq_item::type_id::create("cmd");
core_if_seq_item cloned_item;
$cast(cloned_item, cmd.clone());
m_ap.write(cloned_item);
endtask : run_phase
endclass : core_if_monitor

View file

@ -1,89 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: core_if Sequence item
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class core_if_seq_item extends uvm_sequence_item;
// UVM Factory Registration Macro
`uvm_object_utils(core_if_seq_item)
//------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//------------------------------------------
// TODO: set data members
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "core_if_seq_item");
super.new(name);
endfunction
function void do_copy(uvm_object rhs);
core_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_fatal("do_copy", "cast of rhs object failed")
end
super.do_copy(rhs);
// Copy over data members:
// e.g.:
// operator = rhs_.operator;
endfunction:do_copy
function bit do_compare(uvm_object rhs, uvm_comparer comparer);
core_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_error("do_copy", "cast of rhs object failed")
return 0;
end
// TODO
return super.do_compare(rhs, comparer); // && operator == rhs_.operator
endfunction:do_compare
function string convert2string();
string s;
$sformat(s, "%s\n", super.convert2string());
// Convert to string function reusing s:
// TODO
// $sformat(s, "%s\n operator\n", s, operator);
return s;
endfunction:convert2string
function void do_print(uvm_printer printer);
if(printer.knobs.sprint == 0) begin
$display(convert2string());
end
else begin
printer.m_string = convert2string();
end
endfunction:do_print
function void do_record(uvm_recorder recorder);
super.do_record(recorder);
// Use the record macros to record the item fields:
// TODO
// `uvm_record_field("operator", operator)
endfunction:do_record
endclass : core_if_seq_item

View file

@ -1,53 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: core_if sequence consisting of core_if_sequence_items
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class core_if_sequence extends uvm_sequence #(core_if_seq_item);
// UVM Factory Registration Macro
`uvm_object_utils(core_if_sequence)
//-----------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//-----------------------------------------------
//------------------------------------------
// Constraints
//------------------------------------------
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "core_if_sequence");
super.new(name);
endfunction
task body;
core_if_seq_item req;
begin
req = core_if_seq_item::type_id::create("req");
start_item(req);
assert(req.randomize());
finish_item(req);
end
endtask:body
endclass : core_if_sequence

View file

@ -1,29 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: core_if Sequencer for core_if_sequence_item
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class core_if_sequencer extends uvm_sequencer #(core_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(core_if_sequencer)
// Standard UVM Methods:
function new(string name="core_if_sequencer", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass: core_if_sequencer

View file

@ -1,64 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: DCache interface
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
// Guard statement proposed by "Easier UVM" (doulos)
`ifndef DCACHE_IF_SV
`define DCACHE_IF_SV
interface dcache_if
(
input clk
);
wire [11:0] address_index; // Index portion of address
wire [43:0] address_tag; // Tag portion of the address
wire [63:0] data_wdata; // Data to be written
wire data_req; // Requests read data
wire data_gnt; // Request has been granted, signals can be changed as
// soon as request has been granted
wire kill_req; // Request to kill the previous request
wire tag_valid; // The tag (or kill request) is valid
wire data_rvalid; // Read data is valid
wire [63:0] data_rdata; // Read data
wire data_we; // Write enable
wire [7:0] data_be; // Byte enable
clocking mck @(posedge clk);
input address_index, address_tag, data_wdata, data_we, data_req, kill_req, tag_valid, data_be;
output data_rvalid, data_rdata, data_gnt;
endclocking
// Memory interface configured as slave
clocking sck @(posedge clk);
output address_index, address_tag, data_wdata, data_we, data_req, kill_req, tag_valid, data_be;
input data_rvalid, data_rdata, data_gnt;
endclocking
clocking pck @(posedge clk);
// default input #1ns output #1ns;
input address_index, address_tag, data_wdata, data_req, data_we, data_be, kill_req, tag_valid,
data_gnt, data_rvalid, data_rdata;
endclocking
modport master (
clocking mck
);
modport slave (
clocking sck
);
endinterface
`endif

View file

@ -1,62 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: Main agent object dcache_if. Builds and instantiates the appropriate
// subcomponents like the monitor, driver etc. all based on the
// agent configuration object.
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class dcache_if_agent extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(dcache_if_agent)
//------------------------------------------
// Data Members
//------------------------------------------
dcache_if_agent_config m_cfg;
//------------------------------------------
// Component Members
//------------------------------------------
uvm_analysis_port #(dcache_if_seq_item) ap;
dcache_if_driver m_driver;
dcache_if_monitor m_monitor;
dcache_if_sequencer m_sequencer;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "dcache_if_agent", uvm_component parent = null);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(dcache_if_agent_config)::get(this, "", "dcache_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration dcache_if_agent_config from uvm_config_db. Have you set() it?")
if (m_cfg.active == UVM_ACTIVE)
m_driver = dcache_if_driver::type_id::create("m_driver", this);
m_sequencer = dcache_if_sequencer::type_id::create("m_sequencer", this);
m_monitor = dcache_if_monitor::type_id::create("m_monitor", this);
endfunction : build_phase
function void connect_phase(uvm_phase phase);
if (m_cfg.active == UVM_ACTIVE) begin
m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
m_driver.m_cfg = m_cfg;
end
// m_monitor.ap.connect(m_cov_monitor.analysis_port)
m_monitor.m_cfg = m_cfg;
endfunction: connect_phase
endclass : dcache_if_agent

View file

@ -1,39 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: Agent configuration object dcache_if
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class dcache_if_agent_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(dcache_if_agent_config)
// Virtual Interface
virtual dcache_if m_vif;
// Is this a master or a slave interface
dcache_if_config_t dcache_if_config;
//------------------------------------------
// Data Members
//------------------------------------------
// Is the agent active or passive
uvm_active_passive_enum active = UVM_ACTIVE;
// Standard UVM Methods:
function new(string name = "dcache_if_agent_config");
super.new(name);
endfunction : new
endclass : dcache_if_agent_config

View file

@ -1,51 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: dcache_if_agent package - compile unit
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
package dcache_if_agent_pkg;
// configure the slave memory interface
// 1. either as a slave with random grant response
// 2. as a master interface making random data requests
// 3. as a slave with no grant randomization
// 4. replay data
typedef enum {
SLAVE, SLAVE_REPLAY, SLAVE_NO_RANDOM, MASTER
} dcache_if_config_t;
// Mode of request either read or write
typedef enum {
READ, WRITE
} mode_t;
// UVM Import
import uvm_pkg::*;
`include "uvm_macros.svh"
// Sequence item to model transactions
`include "dcache_if_seq_item.svh"
// Agent configuration object
`include "dcache_if_agent_config.svh"
// Driver
`include "dcache_if_driver.svh"
// Coverage monitor
// `include "dcache_if_coverage_monitor.svh"
// Monitor that includes analysis port
`include "dcache_if_monitor.svh"
// Sequencer
`include "dcache_if_sequencer.svh"
// Main agent
`include "dcache_if_agent.svh"
// Sequence
`include "dcache_if_sequence.svh"
endpackage: dcache_if_agent_pkg

View file

@ -1,155 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: Driver for interface dcache_if
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class dcache_if_driver extends uvm_driver #(dcache_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(dcache_if_driver)
// Virtual Interface
virtual dcache_if m_vif;
//---------------------
// Data Members
//---------------------
dcache_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "dcache_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
dcache_if_seq_item cmd;
logic [11:0] address_index [$];
logic [43:0] address_tag [$];
logic [55:0] address_out;
semaphore lock = new(1);
// --------------
// Slave Port
// --------------
// this driver is configured as a SLAVE
if (m_cfg.dcache_if_config inside {SLAVE, SLAVE_REPLAY, SLAVE_NO_RANDOM}) begin
// grant process is combinatorial
fork
slave_gnt: begin
m_vif.mck.data_gnt <= 1'b1;
// we don't to give random grants
// instead we always grant immediately
if (m_cfg.dcache_if_config != SLAVE_NO_RANDOM) begin
forever begin
// randomize grant delay - the grant may come in the same clock cycle
repeat ($urandom_range(0,3)) @(m_vif.mck);
m_vif.mck.data_gnt <= 1'b1;
repeat ($urandom_range(0,3)) @(m_vif.mck);
m_vif.mck.data_gnt <= 1'b0;
end
end
end
slave_serve: begin
m_vif.mck.data_rdata <= 32'b0;
// apply stimuli for instruction interface
forever begin
@(m_vif.mck)
m_vif.mck.data_rvalid <= 1'b0;
fork
// replay interface
mem_read: begin
// we've got a new request
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);
// 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(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
m_vif.mck.data_rvalid <= 1'b0;
end
mem_write: begin
end
join_none
end
end
join_none
// although no other option exist lets be specific about its purpose
// -> this is a master interface
// --------------
// Master Port
// --------------
end else if (m_cfg.dcache_if_config == MASTER) begin
// request a read
// initial statements, sane resets
m_vif.sck.data_req <= 1'b0;
m_vif.sck.address_index <= 12'b0;
m_vif.sck.address_tag <= 44'b0;
m_vif.sck.data_be <= 7'b0;
m_vif.sck.data_we <= 1'b0;
m_vif.sck.tag_valid <= 1'b0;
m_vif.sck.kill_req <= 1'b0;
m_vif.sck.data_wdata <= 64'b0;
// request read or write
// we don't care about results at this point
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.data_req <= 1'b0;
// delay the next request
repeat (cmd.requestDelay) @(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);
seq_item_port.item_done();
endtask : run_phase
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(dcache_if_agent_config)::get(this, "", "dcache_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration dcache_if_agent_config from uvm_config_db. Have you set() it?")
m_vif = m_cfg.m_vif;
endfunction: build_phase
endclass : dcache_if_driver

View file

@ -1,122 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: dcache_if Monitor, monitors the DUT's pins and writes out
// appropriate sequence items as defined for this particular dut
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class dcache_if_monitor extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(dcache_if_monitor)
// analysis port
uvm_analysis_port #(dcache_if_seq_item) m_ap;
// Virtual Interface
virtual dcache_if m_vif;
mailbox address_mbx;
mailbox data_mbx;
//---------------------
// Data Members
//---------------------
dcache_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "dcache_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(dcache_if_agent_config)::get(this, "", "dcache_if_agent_config", m_cfg) )
`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
function void connect_phase(uvm_phase phase);
// connect virtual interface
m_vif = m_cfg.m_vif;
endfunction
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]";
mailbox address_index = new();
logic [11:0] index;
logic [7:0] be [$];
logic [63:0] wdata [$];
dcache_if_seq_item cmd = dcache_if_seq_item::type_id::create("cmd");
// 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
address_index.put(m_vif.pck.address_index);
be.push_back(m_vif.pck.data_be);
wdata.push_back(m_vif.pck.data_wdata);
end
end
// 2. Thread
// detect a valid tag and save it
tag_valid: begin
forever begin
address_index.get(index);
@(m_vif.pck);
// save tag for later use
if (!m_vif.pck.kill_req)
address_mbx.put({m_vif.pck.address_tag, index});
else begin // remove the index if the request has been aborted
void'(be.pop_front());
void'(wdata.pop_front());
end
end
end
// 3. thread wait for valid data
read_valid: begin
forever begin
@(m_vif.pck iff m_vif.pck.data_rvalid && !m_vif.pck.kill_req);
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();
cmd.wdata = wdata.pop_front();
// 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
endtask : run_phase
endclass : dcache_if_monitor

View file

@ -1,107 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: dcache_if Sequence item
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class dcache_if_seq_item extends uvm_sequence_item;
// UVM Factory Registration Macro
`uvm_object_utils(dcache_if_seq_item)
//------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//------------------------------------------
rand logic [63:0] address;
rand logic [63:0] data;
rand logic [63:0] wdata;
rand logic [7:0] be;
rand int requestDelay;
mode_t mode;
logic isSlaveAnswer;
constraint delay_bounds {
requestDelay inside {[0:10]};
}
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "dcache_if_seq_item");
super.new(name);
endfunction
function void do_copy(uvm_object rhs);
dcache_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_fatal("do_copy", "cast of rhs object failed")
end
super.do_copy(rhs);
// Copy over data members:
// e.g.:
address = rhs_.address;
data = rhs_.data;
be = rhs_.be;
mode = rhs_.mode;
wdata = rhs_.wdata;
isSlaveAnswer = rhs_.isSlaveAnswer;
endfunction : do_copy
function bit do_compare(uvm_object rhs, uvm_comparer comparer);
dcache_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_error("do_copy", "cast of rhs object failed")
return 0;
end
return super.do_compare(rhs, comparer)
&& address == rhs_.address
&& data == rhs_.data
&& be == rhs_.be
&& mode == rhs_.mode
&& wdata == rhs_.wdata;
endfunction : do_compare
function string convert2string();
string s;
$sformat(s, "%s\n", super.convert2string());
$sformat(s, "%s\nMode: %s\nAddress: %0h\nData: %0h\nBE: %0h\nwdata: %0h\nisSlaveAnswer: %h", s, mode.name, address, data, be, wdata, isSlaveAnswer);
return s;
endfunction:convert2string
function void do_print(uvm_printer printer);
if(printer.knobs.sprint == 0) begin
$display(convert2string());
end
else begin
printer.m_string = convert2string();
end
endfunction : do_print
function void do_record(uvm_recorder recorder);
super.do_record(recorder);
// Use the record macros to record the item fields:
`uvm_record_field("mode", mode)
`uvm_record_field("address", address)
`uvm_record_field("data", data)
`uvm_record_field("be", be)
`uvm_record_field("wdate", be)
endfunction:do_record
endclass : dcache_if_seq_item

View file

@ -1,53 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: dcache_if sequence consisting of dcache_if_sequence_items
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class dcache_if_sequence extends uvm_sequence #(dcache_if_seq_item);
// UVM Factory Registration Macro
`uvm_object_utils(dcache_if_sequence)
//-----------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//-----------------------------------------------
//------------------------------------------
// Constraints
//------------------------------------------
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "dcache_if_sequence");
super.new(name);
endfunction
task body;
dcache_if_seq_item req;
begin
req = dcache_if_seq_item::type_id::create("req");
start_item(req);
assert(req.randomize());
finish_item(req);
end
endtask:body
endclass : dcache_if_sequence

View file

@ -1,29 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: dcache_if Sequencer for dcache_if_sequence_item
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class dcache_if_sequencer extends uvm_sequencer #(dcache_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(dcache_if_sequencer)
// Standard UVM Methods:
function new(string name="dcache_if_sequencer", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass: dcache_if_sequencer

View file

@ -1,49 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 14.5.2017
// Description: Fetch FIFO interface
//
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
`ifndef FETCH_FIFO_IF_SV
`define FETCH_FIFO_IF_SV
import ariane_pkg::*;
interface fetch_fifo_if (
input clk
);
wire flush;
wire [$bits(branchpredict_sbe)-1:0] in_branch_predict;
wire [63:0] in_addr;
wire [31:0] in_rdata;
wire in_valid;
wire in_ready;
wire [$bits(fetch_entry)-1:0] fetch_entry;
wire out_valid;
wire out_ready;
clocking mck @(posedge clk);
input in_ready, fetch_entry, out_valid;
output flush, in_branch_predict, in_addr, in_rdata, in_valid, out_ready;
endclocking
clocking pck @(posedge clk);
input in_ready, fetch_entry, out_valid,
flush, in_branch_predict, in_addr, in_rdata, in_valid, out_ready;
endclocking
endinterface
`endif

View file

@ -1,47 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 24.4.2017
// Description: FIFO interface
//
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
`ifndef FIFO_IF_SV
`define FIFO_IF_SV
interface fifo_if #(parameter type dtype = logic[7:0])
(input clk);
wire full;
wire empty;
dtype wdata;
wire push;
dtype rdata;
wire pop;
clocking mck @(posedge clk);
input full, empty, rdata;
output wdata, push, pop;
endclocking
clocking sck @(posedge clk);
input wdata, push, pop;
output full, empty, rdata;
endclocking
clocking pck @(posedge clk);
input wdata, push, pop, full, empty, rdata;
endclocking
endinterface
`endif

View file

@ -1,3 +0,0 @@
# UVM Agent logic for Functional Units
Logic for all functional unit tests is contained in here.

View file

@ -1,43 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 3/18/2017
// Description: Generic functional unit interface (fu if)
// The interface can be used in Master or Slave mode.
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// Guard statement proposed by "Easier UVM" (doulos)
`ifndef ALU_IF__SV
`define ALU_IF__SV
interface fu_if #(parameter int OPERATOR_SIZE = 8, parameter int OPERAND_SIZE = 64)(input clk);
wire [OPERATOR_SIZE-1:0] operator; // FU operation
wire [OPERAND_SIZE-1:0] operand_a; // Operand A
wire [OPERAND_SIZE-1:0] operand_b; // Operand B
wire [OPERAND_SIZE-1:0] operand_c; // Operand C
wire [OPERAND_SIZE-1:0] result; // Result
wire comparison_result; // Comparison result
wire valid; // Result is valid, ready to accept new request
wire ready; // Sink is ready
// FU interface configured as master
clocking mck @(posedge clk);
input operator, operand_a, operand_b, operand_c, ready;
output result, comparison_result, valid;
endclocking
// FU interface configured as slave
clocking sck @(posedge clk);
output operator, operand_a, operand_b, operand_c, ready;
input result, comparison_result, valid;
endclocking
// FU interface configured in passive mode
clocking pck @(posedge clk);
input operator, operand_a, operand_b, operand_c, result, ready;
endclocking
modport master (clocking mck);
modport slave (clocking sck);
modport passive (clocking pck);
endinterface
`endif

View file

@ -1,46 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/20/2016
// Description: This is the main memory interface agent.
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class fu_if_agent extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(fu_if_agent)
//------------------------------------------
// Data Members
//------------------------------------------
fu_if_agent_config m_cfg;
//------------------------------------------
// Component Members
//------------------------------------------
uvm_analysis_port #(fu_if_seq_item) ap;
fu_if_driver m_driver;
fu_if_monitor m_monitor;
fu_if_sequencer m_sequencer;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "fu_if_agent", uvm_component parent = null);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(fu_if_agent_config)::get(this, "", "fu_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration fu_if_agent_config from uvm_config_db. Have you set() it?")
m_driver = fu_if_driver::type_id::create("m_driver", this);
m_sequencer = fu_if_sequencer::type_id::create("m_sequencer", this);
m_monitor = fu_if_monitor::type_id::create("m_monitor", this);
endfunction : build_phase
function void connect_phase(uvm_phase phase);
m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
// m_monitor.ap.connect(m_cov_monitor.analysis_port)
m_driver.m_cfg = m_cfg;
m_monitor.m_cfg = m_cfg;
endfunction: connect_phase
endclass : fu_if_agent

View file

@ -1,29 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/20/2016
// Description: Agent configuration object.
// This object is used by the agent to modularize the build and connect process.
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class fu_if_agent_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(fu_if_agent_config)
// Virtual Interface
virtual fu_if fu;
//------------------------------------------
// Data Members
//------------------------------------------
// Is the agent active or passive
uvm_active_passive_enum active = UVM_ACTIVE;
// Standard UVM Methods:
function new(string name = "fu_if_agent_config");
super.new(name);
endfunction : new
endclass : fu_if_agent_config

View file

@ -1,30 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/20/2016
// Description: Encapsulates the whole memory agent into one package by including
// all the necessary files.
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
package fu_if_agent_pkg;
// UVM Import
import uvm_pkg::*;
`include "uvm_macros.svh"
// Sequence item to model transactions
`include "fu_if_seq_item.svh"
// Agent configuration object
`include "fu_if_agent_config.svh"
// Driver
`include "fu_if_driver.svh"
// Coverage monitor
// `include "fu_if_coverage_monitor.svh"
// Monitor that includes analysis port
`include "fu_if_monitor.svh"
// Sequencer
`include "fu_if_sequencer.svh"
// Main agent
`include "fu_if_agent.svh"
// Sequence
`include "fu_if_seq.svh"
endpackage: fu_if_agent_pkg

View file

@ -1,57 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/21/2016
// Description: Driver of the memory interface
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class fu_if_driver extends uvm_driver #(fu_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(fu_if_driver)
// Virtual Interface
virtual fu_if fu;
//---------------------
// Data Members
//---------------------
fu_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "fu_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
fu_if_seq_item cmd;
fork
forever begin : cmd_loop
shortint unsigned result;
// using clocking blocks this is possible
seq_item_port.get_next_item(cmd);
fu.sck.operand_a <= cmd.operand_a;
fu.sck.operand_b <= cmd.operand_b;
fu.sck.operand_c <= cmd.operand_c;
fu.sck.operator <= cmd.operator;
@(fu.sck)
cmd.result = fu.sck.result;
cmd.compare_result = fu.sck.comparison_result;
seq_item_port.item_done();
end : cmd_loop
join_none
endtask : run_phase
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(fu_if_agent_config)::get(this, "", "fu_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration fu_if_agent_config from uvm_config_db. Have you set() it?")
fu = m_cfg.fu;
endfunction: build_phase
endclass : fu_if_driver

View file

@ -1,63 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/21/2016
// Description: Driver of the memory interface
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class fu_if_monitor extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(fu_if_monitor)
// analysis port
uvm_analysis_port #(fu_if_seq_item) ap;
// Virtual Interface
virtual fu_if fu;
//---------------------
// Data Members
//---------------------
fu_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "fu_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(fu_if_agent_config)::get(this, "", "fu_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration fu_if_agent_config from uvm_config_db. Have you set() it?")
ap = new("ap", this);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
// connect virtual interface
fu = m_cfg.fu;
endfunction
task run_phase(uvm_phase phase);
fu_if_seq_item cmd = fu_if_seq_item::type_id::create("cmd");
fu_if_seq_item cloned_item;
forever begin : cmd_loop
longint result;
cmd.operator = fu.pck.operator;
cmd.operand_a = fu.pck.operand_a;
cmd.operand_b = fu.pck.operand_b;
cmd.operand_c = fu.pck.operand_c;
cmd.result = fu.pck.result;
@(fu.pck)
$cast(cloned_item, cmd.clone());
ap.write(cloned_item);
end : cmd_loop
endtask : run_phase
endclass : fu_if_monitor

View file

@ -1,44 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/21/2016
// Description: Memory interface sequence
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class fu_if_seq extends uvm_sequence #(fu_if_seq_item);
// UVM Factory Registration Macro
`uvm_object_utils(fu_if_seq)
//-----------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//-----------------------------------------------
//------------------------------------------
// Constraints
//------------------------------------------
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "fu_if_seq");
super.new(name);
endfunction
task body;
fu_if_seq_item req;
begin
req = fu_if_seq_item::type_id::create("req");
start_item(req);
assert(req.randomize());
finish_item(req);
end
endtask:body
endclass:fu_if_seq

View file

@ -1,97 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/21/2016
// Description: Sequence contains the necessary fields along with randomization constraints
// Requests can be arbitrarily delayed.
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class fu_if_seq_item extends uvm_sequence_item;
// UVM Factory Registration Macro
`uvm_object_utils(fu_if_seq_item)
//------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//------------------------------------------
logic[7:0] operator;
rand logic[64:0] operand_a;
rand logic[64:0] operand_b;
rand logic[64:0] operand_c;
logic[64:0] result;
logic compare_result;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "fu_if_seq_item");
super.new(name);
endfunction
function void do_copy(uvm_object rhs);
fu_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_fatal("do_copy", "cast of rhs object failed")
end
super.do_copy(rhs);
// Copy over data members:
operator = rhs_.operator;
operand_a = rhs_.operand_a;
operand_b = rhs_.operand_b;
operand_c = rhs_.operand_c;
result = rhs_.result;
compare_result = rhs_.compare_result;
endfunction:do_copy
function bit do_compare(uvm_object rhs, uvm_comparer comparer);
fu_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_error("do_copy", "cast of rhs object failed")
return 0;
end
return super.do_compare(rhs, comparer) &&
operator == rhs_.operator &&
operand_a == rhs_.operand_a &&
operand_b == rhs_.operand_b &&
operand_c == rhs_.operand_c;
endfunction:do_compare
function string convert2string();
string s;
$sformat(s, "%s\n", super.convert2string());
// Convert to string function reusing s:
$sformat(s, "%s\n operator\t%0h\n operandA\t%0h\n operandB\t%0h\n operandC\t%0h\n result\t%0h\n", s, operator, operand_a, operand_b, operand_c, result);
return s;
endfunction:convert2string
function void do_print(uvm_printer printer);
if(printer.knobs.sprint == 0) begin
$display(convert2string());
end
else begin
printer.m_string = convert2string();
end
endfunction:do_print
function void do_record(uvm_recorder recorder);
super.do_record(recorder);
// Use the record macros to record the item fields:
`uvm_record_field("operator", operator)
`uvm_record_field("operand_a", operand_a)
`uvm_record_field("operand_b", operand_b)
`uvm_record_field("operand_c", operand_c)
endfunction:do_record
endclass : fu_if_seq_item

View file

@ -1,20 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/21/2016
// Description: Sequencer
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class fu_if_sequencer extends uvm_sequencer #(fu_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(fu_if_sequencer)
// Standard UVM Methods:
function new(string name="fu_if_sequencer", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass: fu_if_sequencer

View file

@ -1,59 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: LSU interface
//
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// Guard statement proposed by "Easier UVM" (doulos)
`ifndef LSU_IF_SV
`define LSU_IF_SV
import ariane_pkg::*;
interface lsu_if #(
parameter int OPERAND_SIZE = 64
)
(
input clk
);
fu_op operator; // FU operation
wire [OPERAND_SIZE-1:0] operand_a; // Operand A
wire [OPERAND_SIZE-1:0] operand_b; // Operand B
wire [OPERAND_SIZE-1:0] imm; // Operand B
wire [OPERAND_SIZE-1:0] result; // Result
wire [TRANS_ID_BITS-1:0] lsu_trans_id_id; // transaction id from ID
wire [TRANS_ID_BITS-1:0] lsu_trans_id_wb; // transaction id to WB
// LSU control signals
wire commit;
wire source_valid; // Source operands are valid
wire result_valid; // Result is valid, ready to accept new request
wire ready; // Sink is ready
// exceptions
wire [$bits(exception)-1:0] exception;
// FU interface configured as master
clocking mck @(posedge clk);
default input #1ns output #1ns;
output operator, operand_a, operand_b, imm, source_valid, commit, lsu_trans_id_id;
input result, lsu_trans_id_wb, result_valid, ready, exception;
endclocking
// FU interface configured as slave
clocking sck @(posedge clk);
default input #1ns output #1ns;
input operator, operand_a, operand_b, imm, source_valid, commit, lsu_trans_id_id;
output result, lsu_trans_id_wb, result_valid, ready, exception;
endclocking
// FU interface configured in passive mode
clocking pck @(posedge clk);
input operator, operand_a, operand_b, imm, source_valid, commit, lsu_trans_id_id,
result, lsu_trans_id_wb, result_valid, ready, exception ;
endclocking
modport master (clocking mck);
modport slave (clocking sck);
modport passive (clocking pck);
endinterface
`endif

View file

@ -1,57 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: Main agent object lsu_if. Builds and instantiates the appropriate
// subcomponents like the monitor, driver etc. all based on the
// agent configuration object.
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class lsu_if_agent extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(lsu_if_agent)
//------------------------------------------
// Data Members
//------------------------------------------
lsu_if_agent_config m_cfg;
//------------------------------------------
// Component Members
//------------------------------------------
uvm_analysis_port #(lsu_if_seq_item) ap;
lsu_if_driver m_driver;
lsu_if_monitor m_monitor;
lsu_if_sequencer m_sequencer;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "lsu_if_agent", uvm_component parent = null);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(lsu_if_agent_config)::get(this, "", "lsu_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration lsu_if_agent_config from uvm_config_db. Have you set() it?")
m_driver = lsu_if_driver::type_id::create("m_driver", this);
m_sequencer = lsu_if_sequencer::type_id::create("m_sequencer", this);
m_monitor = lsu_if_monitor::type_id::create("m_monitor", this);
endfunction : build_phase
function void connect_phase(uvm_phase phase);
m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
// m_monitor.ap.connect(m_cov_monitor.analysis_port)
m_driver.m_cfg = m_cfg;
m_monitor.m_cfg = m_cfg;
endfunction: connect_phase
endclass : lsu_if_agent

View file

@ -1,37 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: Agent configuration object lsu_if
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class lsu_if_agent_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(lsu_if_agent_config)
// Virtual Interface
virtual lsu_if m_vif;
//------------------------------------------
// Data Members
//------------------------------------------
// Is the agent active or passive
uvm_active_passive_enum active = UVM_ACTIVE;
// Standard UVM Methods:
function new(string name = "lsu_if_agent_config");
super.new(name);
endfunction : new
endclass : lsu_if_agent_config

View file

@ -1,40 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: lsu_if_agent package - compile unit
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
package lsu_if_agent_pkg;
// UVM Import
import uvm_pkg::*;
// import the ariane package for the various data-types
import ariane_pkg::*;
`include "uvm_macros.svh"
// Sequence item to model transactions
`include "lsu_if_seq_item.svh"
// Agent configuration object
`include "lsu_if_agent_config.svh"
// Driver
`include "lsu_if_driver.svh"
// Coverage monitor
// `include "lsu_if_coverage_monitor.svh"
// Monitor that includes analysis port
`include "lsu_if_monitor.svh"
// Sequencer
`include "lsu_if_sequencer.svh"
// Main agent
`include "lsu_if_agent.svh"
// Sequence
`include "lsu_if_sequence.svh"
endpackage: lsu_if_agent_pkg

View file

@ -1,90 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: Driver for interface lsu_if
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class lsu_if_driver extends uvm_driver #(lsu_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(lsu_if_driver)
// Virtual Interface
virtual lsu_if m_vif;
//---------------------
// Data Members
//---------------------
lsu_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "lsu_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
semaphore lock = new(1);
lsu_if_seq_item cmd;
// reset values
m_vif.mck.lsu_trans_id_id <= 'b0;
m_vif.mck.source_valid <= 1'b0;
m_vif.mck.imm <= 'b0;
m_vif.mck.operator <= ADD;
m_vif.mck.operand_a <= 'b0;
m_vif.mck.operand_b <= 'b0;
m_vif.mck.commit <= 1'b0;
forever begin
// if the LSU is ready apply a new stimuli
@(m_vif.mck);
if (m_vif.mck.ready) begin
seq_item_port.get_next_item(cmd);
// we potentially want to wait a couple of cycles before applying
// a new request
repeat(cmd.requestDelay) @(m_vif.mck);
// the data we apply is valid
m_vif.mck.lsu_trans_id_id <= cmd.trans_id;
m_vif.mck.source_valid <= 1'b1;
m_vif.mck.imm <= cmd.imm;
m_vif.mck.operator <= cmd.operator;
m_vif.mck.operand_a <= cmd.operandA;
m_vif.mck.operand_b <= cmd.operandB;
@(m_vif.mck);
// spawn a commit thread that will eventually commit this instruction
case (cmd.operator)
SD, SW, SH, SB:
fork
commit_thread: begin
lock.get(1);
@(m_vif.mck);
m_vif.mck.commit <= 1'b1;
@(m_vif.mck);
m_vif.mck.commit <= 1'b0;
lock.put(1);
end
join_none
endcase
m_vif.mck.source_valid <= 1'b0;
seq_item_port.item_done();
end else
m_vif.mck.source_valid <= 1'b0;
end
endtask : run_phase
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(lsu_if_agent_config)::get(this, "", "lsu_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration lsu_if_agent_config from uvm_config_db. Have you set() it?")
m_vif = m_cfg.m_vif;
endfunction: build_phase
endclass : lsu_if_driver

View file

@ -1,62 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: lsu_if Monitor, monitors the DUT's pins and writes out
// appropriate sequence items as defined for this particular dut
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class lsu_if_monitor extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(lsu_if_monitor)
// analysis port
uvm_analysis_port #(lsu_if_seq_item) m_ap;
// Virtual Interface
virtual lsu_if m_vif;
//---------------------
// Data Members
//---------------------
lsu_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "lsu_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(lsu_if_agent_config)::get(this, "", "lsu_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration lsu_if_agent_config from uvm_config_db. Have you set() it?")
m_ap = new("m_ap", this);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
// connect virtual interface
m_vif = m_cfg.m_vif;
endfunction
task run_phase(uvm_phase phase);
lsu_if_seq_item cmd = lsu_if_seq_item::type_id::create("cmd");
lsu_if_seq_item cloned_item;
$cast(cloned_item, cmd.clone());
m_ap.write(cloned_item);
endtask : run_phase
endclass : lsu_if_monitor

View file

@ -1,131 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: lsu_if Sequence item
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class lsu_if_seq_item extends uvm_sequence_item;
// UVM Factory Registration Macro
`uvm_object_utils(lsu_if_seq_item)
//------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//------------------------------------------
rand fu_op operator;
rand logic [63:0] operandA;
rand logic [63:0] operandB;
rand logic [63:0] imm;
rand logic [TRANS_ID_BITS-1:0] trans_id;
rand int requestDelay;
logic [63:0] result;
const fu_op allowed_ops[] = {LD, SD, LW, LWU, SW, LH, LHU, SH, LB, SB, LBU};
// constraint the delay we allow
constraint delay_bounds {
requestDelay inside {[0:10]};
}
// constraint the allowed operators
constraint allowed_operations {
operator inside {allowed_ops};
}
constraint base {
operandA[2:0] == 3'b000;
}
// aligned memory constraint
constraint aligned_address {
// constraint to signed or unsigned immediate
imm[62:11] == {52 {imm[63]}};
// constraint aligness
(operator == LD || operator == SD) -> {
imm[3:0] == 3'b000;
}
(operator == LW || operator == LWU || operator == SW) -> {
imm[3:0] == 3'b00;
}
(operator == LH || operator == LHU || operator == SH) -> {
imm[3:0] == 3'b0;
}
}
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "lsu_if_seq_item");
super.new(name);
endfunction
function void do_copy(uvm_object rhs);
lsu_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_fatal("do_copy", "cast of rhs object failed")
end
super.do_copy(rhs);
// Copy over data members:
operator = rhs_.operator;
operandA = rhs_.operandA;
operandB = rhs_.operandA;
imm = rhs_.imm;
result = rhs_.result;
endfunction:do_copy
function bit do_compare(uvm_object rhs, uvm_comparer comparer);
lsu_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_error("do_copy", "cast of rhs object failed")
return 0;
end
// TODO
return super.do_compare(rhs, comparer)
&& operandA == rhs_.operandA
&& operandB == rhs_.operandB
&& imm == rhs_.imm
&& result == rhs_.result;
endfunction:do_compare
function string convert2string();
string s;
$sformat(s, "%s\n", super.convert2string());
// Convert to string function reusing s:
$sformat(s, "%s\n operandA: %0h\noperandB: %0h\imm: %0h\result: %0h\n", s, operandA, operandB, imm, result);
return s;
endfunction:convert2string
function void do_print(uvm_printer printer);
if(printer.knobs.sprint == 0) begin
$display(convert2string());
end
else begin
printer.m_string = convert2string();
end
endfunction:do_print
function void do_record(uvm_recorder recorder);
super.do_record(recorder);
// Use the record macros to record the item fields:
`uvm_record_field("operandA", operandA)
`uvm_record_field("operandB", operandB)
`uvm_record_field("imm", imm)
`uvm_record_field("result", result)
endfunction:do_record
endclass : lsu_if_seq_item

View file

@ -1,53 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: lsu_if sequence consisting of lsu_if_sequence_items
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class lsu_if_sequence extends uvm_sequence #(lsu_if_seq_item);
// UVM Factory Registration Macro
`uvm_object_utils(lsu_if_sequence)
//-----------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//-----------------------------------------------
//------------------------------------------
// Constraints
//------------------------------------------
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "lsu_if_sequence");
super.new(name);
endfunction
task body;
lsu_if_seq_item req;
begin
req = lsu_if_seq_item::type_id::create("req");
start_item(req);
assert(req.randomize());
finish_item(req);
end
endtask:body
endclass : lsu_if_sequence

View file

@ -1,29 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: lsu_if Sequencer for lsu_if_sequence_item
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class lsu_if_sequencer extends uvm_sequencer #(lsu_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(lsu_if_sequencer)
// Standard UVM Methods:
function new(string name="lsu_if_sequencer", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass: lsu_if_sequencer

View file

@ -1,58 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 30.04.2017
// Description: Main agent object mem_if. Builds and instantiates the appropriate
// subcomponents like the monitor, driver etc. all based on the
// agent configuration object.
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class mem_if_agent extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(mem_if_agent)
//------------------------------------------
// Data Members
//------------------------------------------
mem_if_agent_config m_cfg;
//------------------------------------------
// Component Members
//------------------------------------------
uvm_analysis_port #(mem_if_seq_item) ap;
mem_if_driver m_driver;
mem_if_monitor m_monitor;
mem_if_sequencer m_sequencer;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "mem_if_agent", uvm_component parent = null);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
// uvm_config_db #(int)::dump();
if (!uvm_config_db #(mem_if_agent_config)::get(this, "", "mem_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration mem_if_agent_config from uvm_config_db. Have you set() it?")
m_driver = mem_if_driver::type_id::create("m_driver", this);
m_sequencer = mem_if_sequencer::type_id::create("m_sequencer", this);
m_monitor = mem_if_monitor::type_id::create("m_monitor", this);
endfunction : build_phase
function void connect_phase(uvm_phase phase);
m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
// m_monitor.ap.connect(m_cov_monitor.analysis_port)
m_driver.m_cfg = m_cfg;
m_monitor.m_cfg = m_cfg;
endfunction: connect_phase
endclass : mem_if_agent

View file

@ -1,41 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 30.04.2017
// Description: Agent configuration object mem_if
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class mem_if_agent_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(mem_if_agent_config)
//------------------------------------------
// Data Members
//------------------------------------------
// Virtual Interface
virtual mem_if fu;
// Is this a master or a slave interface
mem_if_config mem_if_config;
// configure the path to the memory file from which to serve all read requests
string mem_file;
// Is the agent active or passive
uvm_active_passive_enum active = UVM_ACTIVE;
// Standard UVM Methods:
function new(string name = "mem_if_agent_config");
super.new(name);
endfunction : new
endclass : mem_if_agent_config

View file

@ -1,50 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 30.04.2017
// Description: mem_if_agent package - compile unit
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
package mem_if_agent_pkg;
// configure the slave memory interface
// 1. either as a slave with random grant response
// 2. as a master interface making random data requests
// 3. as a slave with no grant randomization
// 4. replay data
typedef enum {
SLAVE, SLAVE_REPLAY, SLAVE_NO_RANDOM, MASTER
} mem_if_config;
// Mode of request either read or write
typedef enum {
READ, WRITE
} mode_t;
// UVM Import
import uvm_pkg::*;
`include "uvm_macros.svh"
// Sequence item to model transactions
`include "mem_if_seq_item.svh"
// Agent configuration object
`include "mem_if_agent_config.svh"
// Driver
`include "mem_if_driver.svh"
// Coverage monitor
// `include "mem_if_coverage_monitor.svh"
// Monitor that includes analysis port
`include "mem_if_monitor.svh"
// Sequencer
`include "mem_if_sequencer.svh"
// Main agent
`include "mem_if_agent.svh"
// Sequence
`include "mem_if_sequence.svh"
endpackage: mem_if_agent_pkg

View file

@ -1,163 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 30.04.2017
// Description: Driver for interface mem_if
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class mem_if_driver extends uvm_driver #(mem_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(mem_if_driver)
// Virtual Interface
virtual mem_if fu;
// create a 4 kB memory
logic [7:0] rmem [4096];
//---------------------
// Data Members
//---------------------
mem_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "mem_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
task read_mem(logic [64:0] address, string path);
$readmemh(path, rmem, address);
$display("Read instruction memory file @%0h from %s", address, path);
endtask : read_mem
task run_phase(uvm_phase phase);
mem_if_seq_item cmd;
// --------------
// Slave Port
// --------------
// this driver is configured as a SLAVE
if (m_cfg.mem_if_config inside {SLAVE, SLAVE_REPLAY, SLAVE_NO_RANDOM}) begin
logic [63:0] address [$];
logic [63:0] addr;
semaphore lock = new(1);
// we serve all requests from the memory file we store in our configuration object
// read memory file
// TODO: get the filename and address from plusarg
if (m_cfg.mem_if_config inside {SLAVE, SLAVE_NO_RANDOM}) begin
read_mem(64'b0, "test/add_test.v");
end
// grant process is combinatorial
fork
slave_gnt: begin
fu.mck.data_gnt <= 1'b1;
// we don't to give random grants
// instead we always grant immediately
if (m_cfg.mem_if_config != SLAVE_NO_RANDOM) begin
forever begin
// randomize grant delay - the grant may come in the same clock cycle
repeat ($urandom_range(0,3)) @(fu.mck);
fu.mck.data_gnt <= 1'b1;
repeat ($urandom_range(0,3)) @(fu.mck);
fu.mck.data_gnt <= 1'b0;
end
end
end
slave_serve: begin
fu.mck.data_rdata <= 32'b0;
// apply stimuli for instruction interface
forever begin
@(fu.mck)
fu.mck.data_rvalid <= 1'b0;
fork
// replay interface
imem_read: begin
if (fu.pck.data_gnt & fu.mck.data_req) begin
// $display("Time: %t, Pushing", $time);
address.push_back(fu.mck.address);
if (address.size() != 0) begin
// we can wait a couple of cycles here
// but at least one
lock.get(1);
// we give the rvalid in the next cycle if didn't request randomization
if (m_cfg.mem_if_config != SLAVE_NO_RANDOM)
repeat ($urandom_range(1,3)) @(fu.mck);
fu.mck.data_rvalid <= 1'b1;
addr = address.pop_front();
// simply replay the address on the data port
if (m_cfg.mem_if_config == SLAVE_REPLAY)
fu.mck.data_rdata <= addr;
else begin
// read from memory
fu.mck.data_rdata <= {
rmem[$unsigned(addr + 3)],
rmem[$unsigned(addr + 2)],
rmem[$unsigned(addr + 1)],
rmem[$unsigned(addr + 0)]
};
end
lock.put(1);
end else
fu.mck.data_rvalid <= 1'b0;
end
end
imem_write: begin
end
join_none
end
end
join_none
// although no other option exist lets be specific about its purpose
// -> this is a master interface
// --------------
// Master Port
// --------------
end else if (m_cfg.mem_if_config == MASTER) begin
// request a read
// initial statements, sane resets
fu.sck.data_req <= 1'b0;
fu.sck.address <= 64'b0;
fu.sck.data_be <= 7'b0;
fu.sck.data_we <= 1'b0;
fu.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
fu.sck.data_req <= 1'b1;
fu.sck.address <= cmd.address;
fu.sck.data_be <= cmd.be;
fu.sck.data_we <= (cmd.mode == READ) ? 1'b0 : 1'b1;
fu.sck.data_wdata <= cmd.data;
@(fu.sck iff fu.sck.data_gnt);
fu.sck.data_req <= 1'b0;
// delay the next request
repeat(cmd.requestDelay) @(fu.sck);
seq_item_port.item_done();
end
end
endtask : run_phase
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(mem_if_agent_config)::get(this, "", "mem_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration mem_if_agent_config from uvm_config_db. Have you set() it?")
fu = m_cfg.fu;
endfunction: build_phase
endclass : mem_if_driver

View file

@ -1,91 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 30.04.2017
// Description: mem_if Monitor, monitors the DUT's pins and writes out
// appropriate sequence items as defined for this particular dut
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class mem_if_monitor extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(mem_if_monitor)
// analysis port
uvm_analysis_port #(mem_if_seq_item) m_ap;
// Virtual Interface
virtual mem_if fu;
//---------------------
// Data Members
//---------------------
mem_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "mem_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(mem_if_agent_config)::get(this, "", "mem_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration mem_if_agent_config from uvm_config_db. Have you set() it?")
m_ap = new("m_ap", this);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
// connect virtual interface
fu = m_cfg.fu;
endfunction
task run_phase(uvm_phase phase);
logic[63:0] address [$];
logic[7:0] be [$];
mem_if_seq_item cmd = mem_if_seq_item::type_id::create("cmd");
// Monitor
// we should also distinguish between slave and master here
fork
// detect a request
forever begin
// wait until detecting a valid request -> store be and address
@(fu.pck iff (fu.pck.data_gnt && fu.pck.data_req));
// if (m_cfg.mem_if_config == MASTER)
// $display("Pushing Address: %0h", fu.pck.address);
address.push_back(fu.pck.address);
be.push_back(fu.pck.data_be);
end
// request finished send it to the monitor
forever begin
mem_if_seq_item cloned_item;
automatic logic [63:0] addr;
// wait for the rvalid minimum a cycle later
@(fu.pck iff fu.pck.data_rvalid);
addr = address.pop_front();
// if (m_cfg.mem_if_config == MASTER)
// $display("Popping Address: %0h", addr);
cmd.address = addr;
cmd.be = be.pop_front();
cmd.data = fu.pck.data_rdata;
// was this from a master or slave agent monitor?
cmd.isSlaveAnswer = (m_cfg.mem_if_config inside {SLAVE, SLAVE_REPLAY, SLAVE_NO_RANDOM}) ? 1'b1 : 1'b0;
// export the item via the analysis port
$cast(cloned_item, cmd.clone());
m_ap.write(cloned_item);
end
join_none
endtask : run_phase
endclass : mem_if_monitor

View file

@ -1,104 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 30.04.2017
// Description: mem_if Sequence item
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class mem_if_seq_item extends uvm_sequence_item;
// UVM Factory Registration Macro
`uvm_object_utils(mem_if_seq_item)
//------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//------------------------------------------
rand logic [63:0] address;
rand logic [63:0] data;
rand logic [7:0] be;
rand int requestDelay;
mode_t mode;
logic isSlaveAnswer;
constraint delay_bounds {
requestDelay inside {[0:10]};
}
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "mem_if_seq_item");
super.new(name);
endfunction
function void do_copy(uvm_object rhs);
mem_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_fatal("do_copy", "cast of rhs object failed")
end
super.do_copy(rhs);
// Copy over data members:
// e.g.:
address = rhs_.address;
data = rhs_.data;
be = rhs_.be;
mode = rhs_.mode;
isSlaveAnswer = rhs_.isSlaveAnswer;
endfunction:do_copy
function bit do_compare(uvm_object rhs, uvm_comparer comparer);
mem_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_error("do_copy", "cast of rhs object failed")
return 0;
end
return super.do_compare(rhs, comparer)
&& address == rhs_.address
&& data == rhs_.data
&& be == rhs_.be
&& mode == rhs_.mode;
endfunction:do_compare
function string convert2string();
string s;
$sformat(s, "%s\n", super.convert2string());
$sformat(s, "%s\nMode: %s\nAddress: %0h\nData: %0h\nBE: %0h \nisSlaveAnswer: %h", s, mode.name, address, data, be, isSlaveAnswer);
return s;
endfunction:convert2string
function void do_print(uvm_printer printer);
if(printer.knobs.sprint == 0) begin
$display(convert2string());
end
else begin
printer.m_string = convert2string();
end
endfunction:do_print
function void do_record(uvm_recorder recorder);
super.do_record(recorder);
// Use the record macros to record the item fields:
`uvm_record_field("Mode", mode)
`uvm_record_field("Address", address)
`uvm_record_field("Data", data)
`uvm_record_field("BE", be)
endfunction:do_record
endclass : mem_if_seq_item

View file

@ -1,53 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 30.04.2017
// Description: mem_if sequence consisting of mem_if_sequence_items
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class mem_if_sequence extends uvm_sequence #(mem_if_seq_item);
// UVM Factory Registration Macro
`uvm_object_utils(mem_if_sequence)
//-----------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//-----------------------------------------------
//------------------------------------------
// Constraints
//------------------------------------------
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "mem_if_sequence");
super.new(name);
endfunction
task body;
mem_if_seq_item req;
begin
req = mem_if_seq_item::type_id::create("req");
start_item(req);
assert(req.randomize());
finish_item(req);
end
endtask:body
endclass : mem_if_sequence

View file

@ -1,29 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 30.04.2017
// Description: mem_if Sequencer for mem_if_sequence_item
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class mem_if_sequencer extends uvm_sequencer #(mem_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(mem_if_sequencer)
// Standard UVM Methods:
function new(string name="mem_if_sequencer", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass: mem_if_sequencer

View file

@ -1,3 +0,0 @@
# Scoreboard UVM Agent
Logic for all scoreboard tests is contained in here.

View file

@ -1,53 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 3/18/2017
// Description: Scoreboard interface
// The interface can be used in Master or Slave mode.
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// Guard statement proposed by "Easier UVM" (doulos)
`ifndef SCOREBOARD_IF__SV
`define SCOREBOARD_IF_SV
import ariane_pkg::*;
interface scoreboard_if #(parameter int NR_WB_PORTS = 1)(input clk);
wire flush;
wire [31:0][$bits(fu_t)-1:0] rd_clobber;
wire [4:0] rs1_address;
wire [63:0] rs1;
wire rs1_valid;
wire [4:0] rs2_address;
wire [63:0] rs2;
wire rs2_valid;
scoreboard_entry commit_instr;
wire commit_ack;
scoreboard_entry decoded_instr;
wire decoded_instr_valid;
wire decoded_instr_ack;
scoreboard_entry issue_instr;
wire issue_instr_valid;
wire issue_ack;
wire [NR_WB_PORTS-1:0][TRANS_ID_BITS-1:0] trans_id;
wire [NR_WB_PORTS-1:0][63:0] wdata;
wire [NR_WB_PORTS-1:0][$bits(exception)-1:0] ex;
wire [NR_WB_PORTS-1:0] wb_valid;
// Scoreboard interface configured as master
clocking mck @(posedge clk);
default input #1 output #5; // save timing
output flush, rs1_address, rs2_address, commit_ack, decoded_instr, decoded_instr_valid, issue_ack, trans_id, wdata, ex, wb_valid;
input rd_clobber, rs1, rs1_valid, rs2, rs2_valid, commit_instr, issue_instr, issue_instr_valid, decoded_instr_ack;
endclocking
// Scoreboard interface configured in passive mode (-> monitor)
clocking pck @(posedge clk);
input flush, rs1_address, rs2_address, commit_ack, decoded_instr, decoded_instr_valid, issue_ack, trans_id, wdata, ex, wb_valid,
rd_clobber, rs1, rs1_valid, rs2, rs2_valid, commit_instr, issue_instr, issue_instr_valid, decoded_instr_ack;
endclocking
modport master (clocking mck);
modport passive (clocking pck);
endinterface
`endif

View file

@ -1,46 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/20/2016
// Description: This is the main memory interface agent.
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class scoreboard_if_agent extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(scoreboard_if_agent)
//------------------------------------------
// Data Members
//------------------------------------------
scoreboard_if_agent_config m_cfg;
//------------------------------------------
// Component Members
//------------------------------------------
uvm_analysis_port #(scoreboard_if_seq_item) ap;
scoreboard_if_driver m_driver;
scoreboard_if_monitor m_monitor;
scoreboard_if_sequencer m_sequencer;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "scoreboard_if_agent", uvm_component parent = null);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(scoreboard_if_agent_config)::get(this, "", "scoreboard_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration scoreboard_agent_config from uvm_config_db. Have you set() it?")
m_driver = scoreboard_if_driver::type_id::create("m_driver", this);
m_sequencer = scoreboard_if_sequencer::type_id::create("m_sequencer", this);
m_monitor = scoreboard_if_monitor::type_id::create("m_monitor", this);
endfunction : build_phase
function void connect_phase(uvm_phase phase);
m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
// m_monitor.ap.connect(m_cov_monitor.analysis_port)
m_driver.m_cfg = m_cfg;
m_monitor.m_cfg = m_cfg;
endfunction: connect_phase
endclass : scoreboard_if_agent

View file

@ -1,30 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 09/04/2017
// Description: Agent configuration object.
// This object is used by the agent to modularize the build and connect process.
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class scoreboard_if_agent_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(scoreboard_if_agent_config)
// Virtual Interface
virtual scoreboard_if fu;
//------------------------------------------
// Data Members
//------------------------------------------
// Is the agent active or passive
uvm_active_passive_enum active = UVM_ACTIVE;
// Standard UVM Methods:
function new(string name = "scoreboard_if_agent_config");
super.new(name);
endfunction : new
endclass : scoreboard_if_agent_config

View file

@ -1,31 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/20/2016
// Description: Encapsulates the whole memory agent into one package by including
// all the necessary files.
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
package scoreboard_if_agent_pkg;
// UVM Import
import uvm_pkg::*;
import ariane_pkg::*;
`include "uvm_macros.svh"
// Sequence item to model transactions
`include "scoreboard_if_seq_item.svh"
// Agent configuration object
`include "scoreboard_if_agent_config.svh"
// Driver
`include "scoreboard_if_driver.svh"
// Coverage monitor
// `include "scoreboard_if_coverage_monitor.svh"
// Monitor that includes analysis port
`include "scoreboard_if_monitor.svh"
// Sequencer
`include "scoreboard_if_sequencer.svh"
// Main agent
`include "scoreboard_if_agent.svh"
// Sequence
`include "scoreboard_if_seq.svh"
endpackage: scoreboard_if_agent_pkg

View file

@ -1,37 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/21/2016
// Description: Driver of the memory interface
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class scoreboard_if_driver extends uvm_driver #(scoreboard_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(scoreboard_if_driver)
// Virtual Interface
virtual scoreboard_if fu;
//---------------------
// Data Members
//---------------------
scoreboard_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "scoreboard_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
scoreboard_if_seq_item cmd;
endtask : run_phase
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(scoreboard_if_agent_config)::get(this, "", "scoreboard_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration scoreboard_if_agent_config from uvm_config_db. Have you set() it?")
fu = m_cfg.fu;
endfunction: build_phase
endclass : scoreboard_if_driver

View file

@ -1,63 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/21/2016
// Description: Driver of the memory interface
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class scoreboard_if_monitor extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(scoreboard_if_monitor)
// analysis port
uvm_analysis_port #(scoreboard_if_seq_item) ap;
// Virtual Interface
virtual scoreboard_if fu;
//---------------------
// Data Members
//---------------------
scoreboard_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "scoreboard_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(scoreboard_if_agent_config)::get(this, "", "scoreboard_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration scoreboard_if_agent_config from uvm_config_db. Have you set() it?")
ap = new("ap", this);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
// connect virtual interface
fu = m_cfg.fu;
endfunction
task run_phase(uvm_phase phase);
scoreboard_if_seq_item cmd = scoreboard_if_seq_item::type_id::create("cmd");
scoreboard_if_seq_item cloned_item;
forever begin : cmd_loop
// longint result;
// cmd.operator = fu.pck.operator;
// cmd.operand_a = fu.pck.operand_a;
// cmd.operand_b = fu.pck.operand_b;
// cmd.operand_c = fu.pck.operand_c;
// cmd.result = fu.pck.result;
// @(fu.pck)
// $cast(cloned_item, cmd.clone());
// ap.write(cloned_item);
end : cmd_loop
endtask : run_phase
endclass : scoreboard_if_monitor

View file

@ -1,43 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/21/2016
// Description: Scoreboard interface sequence
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class scoreboard_if_seq extends uvm_sequence #(scoreboard_if_seq_item);
// UVM Factory Registration Macro
`uvm_object_utils(scoreboard_if_seq)
//-----------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//-----------------------------------------------
//------------------------------------------
// Constraints
//------------------------------------------
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "scoreboard_if_seq");
super.new(name);
endfunction
task body;
scoreboard_if_seq_item req;
begin
req = scoreboard_if_seq_item::type_id::create("req");
start_item(req);
assert(req.randomize());
finish_item(req);
end
endtask : body
endclass : scoreboard_if_seq

View file

@ -1,89 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/21/2016
// Description: Sequence contains the necessary fields along with randomization constraints
// Requests can be arbitrarily delayed.
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
typedef enum {
ISSUE, COMMIT, PUSH
} scoreboard_op;
class scoreboard_if_seq_item extends uvm_sequence_item;
// UVM Factory Registration Macro
`uvm_object_utils(scoreboard_if_seq_item)
//------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//------------------------------------------
rand scoreboard_op instruction_type;
rand scoreboard_entry scoreboard_entry;
rand int delay;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "scoreboard_if_seq_item");
super.new(name);
endfunction
function void do_copy(uvm_object rhs);
scoreboard_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_fatal("do_copy", "cast of rhs object failed")
end
super.do_copy(rhs);
// Copy over data members:
instruction_type = rhs_.instruction_type;
scoreboard_entry = rhs_.scoreboard_entry;
delay = rhs_.delay;
endfunction:do_copy
function bit do_compare(uvm_object rhs, uvm_comparer comparer);
scoreboard_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_error("do_copy", "cast of rhs object failed")
return 0;
end
return super.do_compare(rhs, comparer) &&
instruction_type == rhs_.instruction_type &&
scoreboard_entry == rhs_.scoreboard_entry &&
delay == rhs_.delay;
endfunction:do_compare
function string convert2string();
string s;
$sformat(s, "%s\n", super.convert2string());
// Convert to string function reusing s:
$sformat(s, "%s Scoreboard: %0h Operation: %s", s, instruction_type.name);
return s;
endfunction:convert2string
function void do_print(uvm_printer printer);
if(printer.knobs.sprint == 0) begin
$display(convert2string());
end
else begin
printer.m_string = convert2string();
end
endfunction:do_print
function void do_record(uvm_recorder recorder);
super.do_record(recorder);
// Use the record macros to record the item fields:
`uvm_record_field("instruction_type", instruction_type)
`uvm_record_field("scoreboard_entry", scoreboard_entry)
`uvm_record_field("delay", delay)
endfunction:do_record
endclass : scoreboard_if_seq_item

View file

@ -1,20 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/21/2016
// Description: Sequencer
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class scoreboard_if_sequencer extends uvm_sequencer #(scoreboard_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(scoreboard_if_sequencer)
// Standard UVM Methods:
function new(string name="scoreboard_if_sequencer", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass: scoreboard_if_sequencer

View file

@ -1,55 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 28.4.2017
// Description: Store Queue Interface
//
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
`ifndef STORE_QUEUE_IF_SV
`define STORE_QUEUE_IF_SV
interface store_queue_if
#( parameter int ADDRESS_SIZE = 64,
parameter int DATA_WIDTH = 64
)
(
input clk
);
wire flush;
wire no_st_pending;
wire [11:0] page_offset;
wire page_offset_matches;
wire commit;
wire ready;
wire store_valid;
wire [ADDRESS_SIZE-1:0] store_paddr;
wire [DATA_WIDTH-1:0] store_data;
wire [DATA_WIDTH/8-1:0] store_be;
clocking mck @(posedge clk);
output flush, commit, store_valid, page_offset, store_paddr, store_data, store_be;
input ready, page_offset_matches, no_st_pending;
endclocking
clocking pck @(posedge clk);
input flush, commit, ready, page_offset, page_offset_matches, store_valid, store_paddr,
store_data, store_be, no_st_pending;
endclocking
endinterface
`endif

View file

@ -1,57 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: Main agent object store_queue_if. Builds and instantiates the appropriate
// subcomponents like the monitor, driver etc. all based on the
// agent configuration object.
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class store_queue_if_agent extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(store_queue_if_agent)
//------------------------------------------
// Data Members
//------------------------------------------
store_queue_if_agent_config m_cfg;
//------------------------------------------
// Component Members
//------------------------------------------
uvm_analysis_port #(store_queue_if_seq_item) ap;
store_queue_if_driver m_driver;
store_queue_if_monitor m_monitor;
store_queue_if_sequencer m_sequencer;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "store_queue_if_agent", uvm_component parent = null);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(store_queue_if_agent_config)::get(this, "", "store_queue_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration store_queue_if_agent_config from uvm_config_db. Have you set() it?")
m_driver = store_queue_if_driver::type_id::create("m_driver", this);
m_sequencer = store_queue_if_sequencer::type_id::create("m_sequencer", this);
m_monitor = store_queue_if_monitor::type_id::create("m_monitor", this);
endfunction : build_phase
function void connect_phase(uvm_phase phase);
m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
// m_monitor.ap.connect(m_cov_monitor.analysis_port)
m_driver.m_cfg = m_cfg;
m_monitor.m_cfg = m_cfg;
endfunction: connect_phase
endclass : store_queue_if_agent

View file

@ -1,37 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: Agent configuration object store_queue_if
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class store_queue_if_agent_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(store_queue_if_agent_config)
// Virtual Interface
virtual store_queue_if m_vif;
//------------------------------------------
// Data Members
//------------------------------------------
// Is the agent active or passive
uvm_active_passive_enum active = UVM_ACTIVE;
// Standard UVM Methods:
function new(string name = "store_queue_if_agent_config");
super.new(name);
endfunction : new
endclass : store_queue_if_agent_config

View file

@ -1,37 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: store_queue_if_agent package - compile unit
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
package store_queue_if_agent_pkg;
// UVM Import
import uvm_pkg::*;
`include "uvm_macros.svh"
// Sequence item to model transactions
`include "store_queue_if_seq_item.svh"
// Agent configuration object
`include "store_queue_if_agent_config.svh"
// Driver
`include "store_queue_if_driver.svh"
// Coverage monitor
// `include "store_queue_if_coverage_monitor.svh"
// Monitor that includes analysis port
`include "store_queue_if_monitor.svh"
// Sequencer
`include "store_queue_if_sequencer.svh"
// Main agent
`include "store_queue_if_agent.svh"
// Sequence
`include "store_queue_if_sequence.svh"
endpackage: store_queue_if_agent_pkg

View file

@ -1,86 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: Driver for interface store_queue_if
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class store_queue_if_driver extends uvm_driver #(store_queue_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(store_queue_if_driver)
// Virtual Interface
virtual store_queue_if m_vif;
//---------------------
// Data Members
//---------------------
store_queue_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "store_queue_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
semaphore sem = new(1);
store_queue_if_seq_item cmd;
// reset assignment
m_vif.mck.store_paddr <= 'b0;
m_vif.mck.store_data <= 'b0;
m_vif.mck.store_be <= 'b0;
m_vif.mck.commit <= 1'b0;
m_vif.mck.store_valid <= 1'b0;
m_vif.mck.flush <= 1'b0;
fork
put_data: begin
forever begin
@(m_vif.mck);
// make a new store request
if (m_vif.mck.ready) begin
seq_item_port.get_next_item(cmd);
m_vif.mck.store_paddr <= cmd.address;
m_vif.mck.store_data <= cmd.data;
m_vif.mck.store_be <= cmd.be;
m_vif.mck.store_valid <= 1'b1;
seq_item_port.item_done();
// fork off a commit task
// commit a couple of cycles later
@(m_vif.mck iff m_vif.pck.store_valid)
fork
commit_block: begin
sem.get(1);
m_vif.mck.commit <= 1'b1;
@(m_vif.mck)
m_vif.mck.commit <= 1'b0;
sem.put(1);
end
join_none
end else begin
m_vif.mck.store_valid <= 1'b0;
end
end
end
join_none
endtask : run_phase
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(store_queue_if_agent_config)::get(this, "", "store_queue_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration store_queue_if_agent_config from uvm_config_db. Have you set() it?")
m_vif = m_cfg.m_vif;
endfunction: build_phase
endclass : store_queue_if_driver

View file

@ -1,70 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: store_queue_if Monitor, monitors the DUT's pins and writes out
// appropriate sequence items as defined for this particular dut
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class store_queue_if_monitor extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(store_queue_if_monitor)
// analysis port
uvm_analysis_port #(store_queue_if_seq_item) m_ap;
// Virtual Interface
virtual store_queue_if m_vif;
//---------------------
// Data Members
//---------------------
store_queue_if_agent_config m_cfg;
// Standard UVM Methods:
function new(string name = "store_queue_if_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(store_queue_if_agent_config)::get(this, "", "store_queue_if_agent_config", m_cfg) )
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration store_queue_if_agent_config from uvm_config_db. Have you set() it?")
m_ap = new("m_ap", this);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
// connect virtual interface
m_vif = m_cfg.m_vif;
endfunction
task run_phase(uvm_phase phase);
store_queue_if_seq_item cmd = store_queue_if_seq_item::type_id::create("cmd");
forever begin
store_queue_if_seq_item cloned_item;
// a new store item request has arrived
@(m_vif.pck iff (m_vif.pck.store_valid && m_vif.pck.ready));
// $display("%t, %0h", $time(), m_vif.pck.store_paddr);
cmd.address = m_vif.pck.store_paddr[55:0];
cmd.data = m_vif.pck.store_data;
cmd.be = m_vif.pck.store_be;
$cast(cloned_item, cmd.clone());
m_ap.write(cloned_item);
end
endtask : run_phase
endclass : store_queue_if_monitor

View file

@ -1,92 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: store_queue_if Sequence item
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class store_queue_if_seq_item extends uvm_sequence_item;
// UVM Factory Registration Macro
`uvm_object_utils(store_queue_if_seq_item)
//------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//------------------------------------------
rand logic [63:0] address;
rand logic [63:0] data;
rand logic [7:0] be;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "store_queue_if_seq_item");
super.new(name);
endfunction
function void do_copy(uvm_object rhs);
store_queue_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_fatal("do_copy", "cast of rhs object failed")
end
super.do_copy(rhs);
// Copy over data members:
address = rhs_.address;
data = rhs_.data;
be = rhs_.be;
endfunction:do_copy
function bit do_compare(uvm_object rhs, uvm_comparer comparer);
store_queue_if_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
`uvm_error("do_copy", "cast of rhs object failed")
return 0;
end
return super.do_compare(rhs, comparer) && rhs_.address == address && rhs_.data == data && rhs_.be == be;
endfunction:do_compare
function string convert2string();
string s;
$sformat(s, "%s\n", super.convert2string());
// Convert to string function reusing s:
$sformat(s, "Address: %0h\nData: %0h\nBE: %0h", this.address, this.data, this.be);
return s;
endfunction:convert2string
function void do_print(uvm_printer printer);
if(printer.knobs.sprint == 0) begin
$display(convert2string());
end
else begin
printer.m_string = convert2string();
end
endfunction:do_print
function void do_record(uvm_recorder recorder);
super.do_record(recorder);
// Use the record macros to record the item fields:
`uvm_record_field("address", address)
`uvm_record_field("data", data)
`uvm_record_field("be", be)
endfunction:do_record
endclass : store_queue_if_seq_item

View file

@ -1,53 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: store_queue_if sequence consisting of store_queue_if_sequence_items
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class store_queue_if_sequence extends uvm_sequence #(store_queue_if_seq_item);
// UVM Factory Registration Macro
`uvm_object_utils(store_queue_if_sequence)
//-----------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//-----------------------------------------------
//------------------------------------------
// Constraints
//------------------------------------------
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "store_queue_if_sequence");
super.new(name);
endfunction
task body;
store_queue_if_seq_item req;
begin
req = store_queue_if_seq_item::type_id::create("req");
start_item(req);
assert(req.randomize());
finish_item(req);
end
endtask:body
endclass : store_queue_if_sequence

View file

@ -1,29 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: store_queue_if Sequencer for store_queue_if_sequence_item
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class store_queue_if_sequencer extends uvm_sequencer #(store_queue_if_seq_item);
// UVM Factory Registration Macro
`uvm_component_utils(store_queue_if_sequencer)
// Standard UVM Methods:
function new(string name="store_queue_if_sequencer", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass: store_queue_if_sequencer

View file

@ -1,63 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 03/19/2017
// Description: Top level testbench module. Instantiates the top level DUT, configures
// the virtual interfaces and starts the test passed by +UVM_TEST+
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
module alu_tb;
import uvm_pkg::*;
// import the main test class
import alu_lib_pkg::*;
import ariane_pkg::*;
logic clk;
logic rstn_i;
localparam OPERATOR_SIZE = 8;
localparam OPERAND_SIZE = 64;
fu_if #(OPERATOR_SIZE, OPERAND_SIZE) alu_if (clk);
// ------------------------
// DUT - Device Under Test
// ------------------------
alu
dut
(
.trans_id_i ( ),
.alu_valid_i ( ),
.operator_i ( fu_op'(alu_if.operator) ),
.operand_a_i ( alu_if.operand_a ),
.operand_b_i ( alu_if.operand_b ),
.result_o ( alu_if.result ),
.alu_valid_o ( ),
.alu_ready_o ( ),
.alu_trans_id_o ( )
);
initial begin
// register the ALU interface
uvm_config_db #(virtual fu_if)::set(null, "uvm_test_top", "fu_vif", alu_if);
end
initial begin
clk = 1'b0;
rstn_i = 1'b0;
repeat(8)
#10ns clk = ~clk;
rstn_i = 1'b1;
forever
#10ns clk = ~clk;
end
initial begin
// print the topology
uvm_top.enable_print_topology = 1;
// Start UVM test
run_test();
end
endmodule

View file

@ -1,111 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 23.05.2017
// Description: Load Store Unit, handles address calculation and memory interface signals
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
module core_mem (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
// Instruction memory/cache
input logic [63:0] instr_if_address_i,
input logic instr_if_data_req_i,
input logic [3:0] instr_if_data_be_i,
output logic instr_if_data_gnt_o,
output logic instr_if_data_rvalid_o,
output logic [63:0] instr_if_data_rdata_o,
// Data memory/cache
input logic [11:0] data_if_address_index_i,
input logic [43:0] data_if_address_tag_i,
input logic [63:0] data_if_data_wdata_i,
input logic data_if_data_req_i,
input logic data_if_data_we_i,
input logic [7:0] data_if_data_be_i,
input logic data_if_kill_req_i,
input logic data_if_tag_valid_i,
output logic data_if_data_gnt_o,
output logic data_if_data_rvalid_o,
output logic [63:0] data_if_data_rdata_o
);
// we always grant the access
localparam ADDRESS_WIDTH = 16;
logic [ADDRESS_WIDTH-1:0] instr_address;
// D$ Mock
logic req, we;
logic [7:0] be;
logic [11:0] index;
logic [63:0] wdata;
logic [55:0] data_address;
assign data_address = {data_if_address_tag_i, index[11:3]};
// we always grant the request
assign instr_if_data_gnt_o = instr_if_data_req_i;
assign instr_address = instr_if_address_i[ADDRESS_WIDTH-1+3:3];
dp_ram #(
.ADDR_WIDTH ( ADDRESS_WIDTH ),
.DATA_WIDTH ( 64 )
) ram_i (
.clk ( clk_i ),
.en_a_i ( 1'b1 ),
.addr_a_i ( instr_address ),
.wdata_a_i ( ), // not connected
.rdata_a_o ( instr_if_data_rdata_o ),
.we_a_i ( 1'b0 ), // r/o interface
.be_a_i ( ),
// data RAM
.en_b_i ( req ),
.addr_b_i ( data_address[ADDRESS_WIDTH-1:0] ),
.wdata_b_i ( wdata ),
.rdata_b_o ( data_if_data_rdata_o ),
.we_b_i ( we ),
.be_b_i ( be )
);
// ----------------------
// DCache Mock Interface
// ----------------------
// give the grant immediately
assign data_if_data_gnt_o = data_if_data_req_i;
assign data_if_data_rvalid_o = req;
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
req <= '0;
be <= '0;
we <= '0;
index <= '0;
wdata <= '0;
end else begin
req <= data_if_data_req_i;
be <= data_if_data_be_i;
we <= data_if_data_we_i;
index <= data_if_address_index_i;
wdata <= data_if_data_wdata_i;
end
end
// Output the rvalid one cycle later, together with the rdata
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_
if(~rst_ni) begin
instr_if_data_rvalid_o <= 1'b0;
end else begin
instr_if_data_rvalid_o <= instr_if_data_req_i;
end
end
endmodule

View file

@ -1,59 +0,0 @@
// Copyright 2015 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the “License”); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
module dp_ram
#(
parameter int ADDR_WIDTH = 8,
parameter int DATA_WIDTH = 64
)(
// Clock and Reset
input logic clk,
input logic en_a_i,
input logic [ADDR_WIDTH-1:0] addr_a_i,
input logic [DATA_WIDTH-1:0] wdata_a_i,
output logic [DATA_WIDTH-1:0] rdata_a_o,
input logic we_a_i,
input logic [DATA_WIDTH/8-1:0] be_a_i,
input logic en_b_i,
input logic [ADDR_WIDTH-1:0] addr_b_i,
input logic [DATA_WIDTH-1:0] wdata_b_i,
output logic [DATA_WIDTH-1:0] rdata_b_o,
input logic we_b_i,
input logic [DATA_WIDTH/8-1:0] be_b_i
);
localparam words = 2**ADDR_WIDTH;
logic [DATA_WIDTH/8-1:0][7:0] mem [words-1:0];
always @(posedge clk) begin
if (en_a_i && we_a_i) begin
for (int i = 0; i < DATA_WIDTH/8; i++) begin
if (be_a_i[i])
mem[addr_a_i][i] <= wdata_a_i[i*8 +: 8];
end
end
rdata_a_o <= mem[addr_a_i];
if (en_b_i && we_b_i) begin
for (int i = 0; i < DATA_WIDTH/8; i++) begin
if (be_b_i[i])
mem[addr_b_i][i] <= wdata_b_i[i*8 +: 8];
end
end
end
// output port 2: combinatorially since we need to mimic a cache interface
assign rdata_b_o = mem[addr_b_i];
endmodule

View file

@ -1,197 +0,0 @@
// Author: Andreas Traber, ACP
// Date: 22/02/2016
// Description: Randomly inject stalls in the instruction interface
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
module random_stalls
(
input logic clk_i,
input logic core_req_i,
output logic core_gnt_o,
input logic [63:0] core_addr_i,
input logic core_we_i,
input logic [ 3:0] core_be_i,
input logic [63:0] core_wdata_i,
output logic [63:0] core_rdata_o,
output logic core_rvalid_o,
output logic data_req_o,
input logic data_gnt_i,
output logic [63:0] data_addr_o,
output logic data_we_o,
output logic [ 3:0] data_be_o,
output logic [63:0] data_wdata_o,
input logic [63:0] data_rdata_i,
input logic data_rvalid_i
);
class rand_wait_cycles;
rand int n;
constraint default_c { n >= 0 ; n < 6;}
endclass
// random staller
typedef struct {
logic [63:0] addr;
logic we;
logic [ 3:0] be;
logic [63:0] wdata;
logic [63:0] rdata;
} stall_mem_t;
mailbox core_reqs = new (4);
mailbox core_resps = new (4);
mailbox core_resps_granted = new (4);
mailbox platform_transfers = new (4);
semaphore req_served = new (1);
// ------------------
// Core Request Side
// ------------------
// Waits for requests and puts them in a queue, does not perform actual
// requests to the platform
initial begin
stall_mem_t mem_acc;
automatic rand_wait_cycles wait_cycles = new ();
int temp;
forever begin
core_gnt_o = 1'b0;
#1;
if (!core_req_i)
continue;
// we got a request, now let's wait for a random number of cycles before
// we give the grant
temp = wait_cycles.randomize();
while(wait_cycles.n != 0) begin
@(posedge clk_i);
wait_cycles.n--;
#1;
end
// block until the we served all outstanding requests
req_served.get();
// we waited for a random number of cycles, let's give the grant
core_gnt_o = 1'b1;
mem_acc.addr = core_addr_i;
mem_acc.be = core_be_i;
mem_acc.we = core_we_i;
mem_acc.wdata = core_wdata_i;
core_reqs.put(mem_acc);
@(posedge clk_i);
core_resps_granted.put(1'b1);
end
end
// ------------------
// Core Response Side
// ------------------
// Waits for a response from the platform and then waits for a random number
// of cycles before giving the rvalid
initial begin
stall_mem_t mem_acc;
automatic rand_wait_cycles wait_cycles = new ();
logic granted;
int temp;
forever begin
@(posedge clk_i);
core_rvalid_o = 1'b0;
core_rdata_o = 'x;
core_resps_granted.get(granted);
core_resps.get(mem_acc);
// we got a response, now let's wait for a random amount of cycles
// we give the grant
temp = wait_cycles.randomize();
while(wait_cycles.n != 0) begin
@(posedge clk_i);
wait_cycles.n--;
end
// put back the semaphore
req_served.put();
// we waited for a random number of cycles, let's give the rvalid
core_rdata_o = mem_acc.rdata;
core_rvalid_o = 1'b1;
end
end
// platform request side
// Waits for requests from the core and then performs the request on the
// platform immediately
// Simulates a "virtual" core
initial begin
stall_mem_t mem_acc;
forever begin
@(posedge clk_i);
data_req_o = 1'b0;
data_addr_o = '0;
data_we_o = 1'b0;
data_be_o = 4'b0;
data_wdata_o = 'x;
core_reqs.get(mem_acc);
data_req_o = 1'b1;
data_addr_o = mem_acc.addr;
data_we_o = mem_acc.we;
data_be_o = mem_acc.be;
data_wdata_o = mem_acc.wdata;
#1;
while(!data_gnt_i) begin
@(posedge clk_i);
#1;
end
platform_transfers.put(mem_acc);
end
end
// platform response side
// Waits for rvalids and puts the responses into the core response mailbox
initial begin
stall_mem_t mem_acc;
forever begin
@(posedge clk_i);
platform_transfers.get(mem_acc);
while(!data_rvalid_i) begin
@(posedge clk_i);
end
mem_acc.rdata = data_rdata_i;
core_resps.put(mem_acc);
end
end
endmodule

View file

@ -1,278 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 15/04/2017
// Description: Top level testbench module. Instantiates the top level DUT, configures
// the virtual interfaces and starts the test passed by +UVM_TEST+
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
import ariane_pkg::*;
import uvm_pkg::*;
import core_lib_pkg::*;
`define DRAM_BASE 64'h80000000
`include "uvm_macros.svh"
module core_tb;
import "DPI-C" function chandle read_elf(string fn);
import "DPI-C" function longint unsigned get_section_address(string symb);
import "DPI-C" function longint unsigned get_section_size(string symb);
import "DPI-C" function longint unsigned get_symbol_address(string symb);
static uvm_cmdline_processor uvcl = uvm_cmdline_processor::get_inst();
localparam int unsigned CLOCK_PERIOD = 20ns;
logic clk_i;
logic rst_ni;
logic rtc_i;
logic display_instr;
longint unsigned cycles;
longint unsigned max_cycles;
debug_if debug_if();
core_if core_if (clk_i);
dcache_if dcache_if (clk_i);
logic [63:0] instr_if_address;
logic instr_if_data_req;
logic [3:0] instr_if_data_be;
logic instr_if_data_gnt;
logic instr_if_data_rvalid;
logic [63:0] instr_if_data_rdata;
logic [11:0] data_if_address_index_i;
logic [43:0] data_if_address_tag_i;
logic [63:0] data_if_data_wdata_i;
logic data_if_data_req_i;
logic data_if_data_we_i;
logic [7:0] data_if_data_be_i;
logic data_if_kill_req_i;
logic data_if_tag_valid_i;
logic data_if_data_gnt_o;
logic data_if_data_rvalid_o;
logic [63:0] data_if_data_rdata_o;
// connect D$ interface
assign dcache_if.address_index = data_if_address_index_i;
assign dcache_if.address_tag = data_if_address_tag_i;
assign dcache_if.data_wdata = data_if_data_wdata_i;
assign dcache_if.data_req = data_if_data_req_i;
assign dcache_if.data_we = data_if_data_we_i;
assign dcache_if.data_be = data_if_data_be_i;
assign dcache_if.kill_req = data_if_kill_req_i;
assign dcache_if.tag_valid = data_if_tag_valid_i;
assign dcache_if.data_gnt = data_if_data_gnt_o;
assign dcache_if.data_rvalid = data_if_data_rvalid_o;
assign dcache_if.data_rdata = data_if_data_rdata_o;
random_stalls instr_stalls_i (
.clk_i ( clk_i ),
.core_req_i ( dut.instr_if_data_req_o ),
.core_addr_i ( dut.instr_if_address_o ),
.core_we_i ( ),
.core_be_i ( ),
.core_wdata_i ( ),
.core_gnt_o ( ),
.core_rdata_o ( ),
.core_rvalid_o ( ),
.data_req_o ( ),
.data_addr_o ( ),
.data_we_o ( ),
.data_be_o ( ),
.data_wdata_o ( ),
.data_gnt_i ( instr_if_data_gnt ),
.data_rdata_i ( instr_if_data_rdata ),
.data_rvalid_i ( instr_if_data_rvalid )
);
initial begin
string rand_mem;
// if the randomize memory interface is set to 1 do so
if(uvcl.get_arg_value("+rand_mem_if", rand_mem) != 0) begin
force dut.instr_if_data_gnt_i = instr_stalls_i.core_gnt_o;
force dut.instr_if_data_rvalid_i = instr_stalls_i.core_rvalid_o;
force dut.instr_if_data_rdata_i = instr_stalls_i.core_rdata_o;
force instr_if_data_req = instr_stalls_i.data_req_o;
force instr_if_address = instr_stalls_i.data_addr_o;
end
end
core_mem core_mem_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.instr_if_address_i ( instr_if_address ),
.instr_if_data_req_i ( instr_if_data_req ),
.instr_if_data_be_i ( instr_if_data_be ),
.instr_if_data_gnt_o ( instr_if_data_gnt ),
.instr_if_data_rvalid_o ( instr_if_data_rvalid ),
.instr_if_data_rdata_o ( instr_if_data_rdata ),
.data_if_address_index_i ( data_if_address_index_i ),
.data_if_address_tag_i ( data_if_address_tag_i ),
.data_if_data_wdata_i ( data_if_data_wdata_i ),
.data_if_data_req_i ( data_if_data_req_i ),
.data_if_data_we_i ( data_if_data_we_i ),
.data_if_data_be_i ( data_if_data_be_i ),
.data_if_kill_req_i ( data_if_kill_req_i ),
.data_if_tag_valid_i ( data_if_tag_valid_i ),
.data_if_data_gnt_o ( data_if_data_gnt_o ),
.data_if_data_rvalid_o ( data_if_data_rvalid_o ),
.data_if_data_rdata_o ( data_if_data_rdata_o )
);
ariane dut (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.rtc_i ( rtc_i ),
.clock_en_i ( core_if.clock_en ),
.test_en_i ( core_if.test_en ),
.fetch_enable_i ( core_if.fetch_enable ),
.core_busy_o ( core_if.core_busy ),
.flush_icache_o ( ),
.ext_perf_counters_i ( ),
.boot_addr_i ( core_if.boot_addr ),
.core_id_i ( core_if.core_id ),
.cluster_id_i ( core_if.cluster_id ),
.instr_if_data_req_o ( instr_if_data_req ),
.instr_if_address_o ( instr_if_address ),
.instr_if_data_be_o ( ),
.instr_if_data_gnt_i ( instr_if_data_gnt ),
.instr_if_data_rvalid_i ( instr_if_data_rvalid ),
.instr_if_data_rdata_i ( instr_if_data_rdata ),
.data_if_address_index_o ( data_if_address_index_i ),
.data_if_address_tag_o ( data_if_address_tag_i ),
.data_if_data_wdata_o ( data_if_data_wdata_i ),
.data_if_data_req_o ( data_if_data_req_i ),
.data_if_data_we_o ( data_if_data_we_i ),
.data_if_data_be_o ( data_if_data_be_i ),
.data_if_kill_req_o ( data_if_kill_req_i ),
.data_if_tag_valid_o ( data_if_tag_valid_i ),
.data_if_data_gnt_i ( data_if_data_gnt_o ),
.data_if_data_rvalid_i ( data_if_data_rvalid_o ),
.data_if_data_rdata_i ( data_if_data_rdata_o ),
.irq_i ( {core_if.irq, core_if.irq} ),
.irq_id_i ( core_if.irq_id ),
.irq_ack_o ( core_if.irq_ack ),
.irq_sec_i ( core_if.irq_sec ),
.sec_lvl_o ( core_if.sec_lvl ),
.debug_req_i ( ),
.debug_gnt_o ( ),
.debug_rvalid_o ( ),
.debug_addr_i ( ),
.debug_we_i ( ),
.debug_wdata_i ( ),
.debug_rdata_o ( ),
.debug_halted_o ( ),
.debug_halt_i ( ),
.debug_resume_i ( )
);
// Clock process
initial begin
clk_i = 1'b0;
rst_ni = 1'b0;
repeat(8)
#(CLOCK_PERIOD/2) clk_i = ~clk_i;
rst_ni = 1'b1;
forever begin
#(CLOCK_PERIOD/2) clk_i = 1'b1;
#(CLOCK_PERIOD/2) clk_i = 1'b0;
if (cycles > max_cycles)
$fatal(1, "Simulation reached maximum cycle count of %d", max_cycles);
cycles++;
end
end
// Real Time Clock
initial begin
rtc_i = 1'b0;
forever
#15.258us rtc_i = ~rtc_i;
end
task preload_memories();
string plus_args [$];
longint unsigned bss_address;
longint unsigned bss_size;
string file;
string file_name;
string base_dir;
string test;
// offset the temporary RAM
logic [63:0] rmem [16384];
// get the file name from a command line plus arg
void'(uvcl.get_arg_value("+BASEDIR=", base_dir));
void'(uvcl.get_arg_value("+ASMTEST=", file_name));
file = {base_dir, "/", file_name};
`uvm_info("Program Loader", $sformatf("Pre-loading memory from file: %s\n", file), UVM_LOW);
// read elf file (DPI call)
void'(read_elf(file));
// get the objdump verilog file to load our memorys
$readmemh({file, ".hex"}, rmem);
// copy double-wordwise from verilog file
for (int i = 0; i < 16384; i++) begin
core_mem_i.ram_i.mem[i] = rmem[i];
end
endtask : preload_memories
program testbench (core_if core_if, dcache_if dcache_if);
longint unsigned begin_signature_address;
longint unsigned tohost_address;
string max_cycle_string;
initial begin
preload_memories();
uvm_config_db #(virtual core_if)::set(null, "uvm_test_top", "core_if", core_if);
uvm_config_db #(virtual dcache_if )::set(null, "uvm_test_top", "dcache_if", dcache_if);
// we are interested in the .tohost ELF symbol in-order to observe end of test signals
tohost_address = get_section_address(".tohost");
begin_signature_address = get_symbol_address("begin_signature");
// pass tohost address to UVM resource DB
uvm_config_db #(longint unsigned)::set(null, "uvm_test_top.m_env.m_eoc", "tohost", tohost_address);
uvm_config_db #(longint unsigned)::set(null, "uvm_test_top.m_env.m_eoc", "begin_signature", ((begin_signature_address -`DRAM_BASE) >> 3));
// print the topology
// uvm_top.enable_print_topology = 1;
// get the maximum cycle count the simulation is allowed to run
if (uvcl.get_arg_value("+max-cycles=", max_cycle_string) == 0) begin
max_cycles = {64{1'b1}};
end else begin
max_cycles = max_cycle_string.atoi();
end
// Start UVM test
run_test();
end
endprogram
testbench tb(core_if, dcache_if);
endmodule

View file

@ -1,95 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 24.4.2017
// Description: Memory Arbiter Testbench
//
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
module dcache_arbiter_tb;
import uvm_pkg::*;
// import the main test class
import mem_arbiter_lib_pkg::*;
logic rst_ni, clk;
dcache_if master[3](clk);
dcache_if slave(clk);
// super hack in assigning the wire a value
// we need to keep all interface signals as wire as
// the simulator does not now if this interface will be used
// as an active or passive device
// only helpful thread so far:
// https://verificationacademy.com/forums/uvm/getting-multiply-driven-warnings-vsim-passive-agent
// logic data_gnt_driver = 'z;
// assign data_gnt = data_gnt_driver & data_req;
dcache_arbiter dut (
.clk_i ( clk ),
.rst_ni ( rst_ni ),
.address_index_o ( slave.address_index ),
.address_tag_o ( slave.address_tag ),
.data_wdata_o ( slave.data_wdata ),
.data_req_o ( slave.data_req ),
.data_we_o ( slave.data_we ),
.data_be_o ( slave.data_be ),
.tag_valid_o ( slave.tag_valid ),
.kill_req_o ( slave.kill_req ),
.data_gnt_i ( slave.data_req & slave.data_gnt ),
.data_rvalid_i ( slave.data_rvalid ),
.data_rdata_i ( slave.data_rdata ),
.address_index_i ( {master[2].address_index, master[1].address_index, master[0].address_index} ),
.address_tag_i ( {master[2].address_tag, master[1].address_tag, master[0].address_tag} ),
.data_wdata_i ( {master[2].data_wdata, master[1].data_wdata, master[0].data_wdata} ),
.data_req_i ( {master[2].data_req, master[1].data_req, master[0].data_req} ),
.data_we_i ( {master[2].data_we, master[1].data_we, master[0].data_we} ),
.data_be_i ( {master[2].data_be, master[1].data_be, master[0].data_be} ),
.tag_valid_i ( {master[2].tag_valid, master[1].tag_valid, master[0].tag_valid} ),
.kill_req_i ( {master[2].kill_req, master[1].kill_req, master[0].kill_req} ),
.data_gnt_o ( {master[2].data_gnt, master[1].data_gnt, master[0].data_gnt} ),
.data_rvalid_o ( {master[2].data_rvalid, master[1].data_rvalid, master[0].data_rvalid} ),
.data_rdata_o ( {master[2].data_rdata, master[1].data_rdata, master[0].data_rdata} )
);
initial begin
clk = 1'b0;
rst_ni = 1'b0;
repeat(8)
#10ns clk = ~clk;
rst_ni = 1'b1;
forever
#10ns clk = ~clk;
end
program testbench (dcache_if master[3], dcache_if slave);
initial begin
// register the memory interface
uvm_config_db #(virtual dcache_if)::set(null, "uvm_test_top", "dcache_if_slave", slave);
uvm_config_db #(virtual dcache_if)::set(null, "uvm_test_top", "dcache_if_master0", master[0]);
uvm_config_db #(virtual dcache_if)::set(null, "uvm_test_top", "dcache_if_master1", master[1]);
uvm_config_db #(virtual dcache_if)::set(null, "uvm_test_top", "dcache_if_master2", master[2]);
// print the topology
uvm_top.enable_print_topology = 1;
// Start UVM test
run_test();
end
endprogram
testbench tb (master, slave);
endmodule

View file

@ -1,121 +0,0 @@
// See LICENSE for details.
#ifndef _ELF_H
#define _ELF_H
#include <stdint.h>
#define IS_ELF(hdr) \
((hdr).e_ident[0] == 0x7f && (hdr).e_ident[1] == 'E' && \
(hdr).e_ident[2] == 'L' && (hdr).e_ident[3] == 'F')
#define IS_ELF32(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 1)
#define IS_ELF64(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 2)
#define PT_LOAD 1
#define SHT_NOBITS 8
typedef struct {
uint8_t e_ident[16];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint32_t e_entry;
uint32_t e_phoff;
uint32_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} Elf32_Ehdr;
typedef struct {
uint32_t sh_name;
uint32_t sh_type;
uint32_t sh_flags;
uint32_t sh_addr;
uint32_t sh_offset;
uint32_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint32_t sh_addralign;
uint32_t sh_entsize;
} Elf32_Shdr;
typedef struct
{
uint32_t p_type;
uint32_t p_offset;
uint32_t p_vaddr;
uint32_t p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t p_flags;
uint32_t p_align;
} Elf32_Phdr;
typedef struct
{
uint32_t st_name;
uint32_t st_value;
uint32_t st_size;
uint8_t st_info;
uint8_t st_other;
uint16_t st_shndx;
} Elf32_Sym;
typedef struct {
uint8_t e_ident[16];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry;
uint64_t e_phoff;
uint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} Elf64_Ehdr;
typedef struct {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr;
uint64_t sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
} Elf64_Shdr;
typedef struct {
uint32_t p_type;
uint32_t p_flags;
uint64_t p_offset;
uint64_t p_vaddr;
uint64_t p_paddr;
uint64_t p_filesz;
uint64_t p_memsz;
uint64_t p_align;
} Elf64_Phdr;
typedef struct {
uint32_t st_name;
uint8_t st_info;
uint8_t st_other;
uint16_t st_shndx;
uint64_t st_value;
uint64_t st_size;
} Elf64_Sym;
#endif

View file

@ -1,100 +0,0 @@
#include "vpi_user.h"
#include "elfdpi.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <stdlib.h>
#include "elf.h"
#include <map>
#include <string>
#include <vpi_user.h>
std::map<std::string, uint64_t> symbols;
std::map<std::string, uint64_t> sections;
std::map<std::string, uint64_t> section_length;
uint64_t get_section_address (const char* symb) {
return sections[symb];
}
uint64_t get_symbol_address (const char* symb) {
return symbols[symb];
}
uint64_t get_section_size (const char* symb) {
return section_length[symb];
}
void* read_elf(const char* fn) {
int fd = open(fn, O_RDONLY);
struct stat s;
// check thtat the file exists
assert(fd != -1);
if (fstat(fd, &s) < 0)
abort();
size_t size = s.st_size;
// map the file to memory
char* buf = (char*)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
assert(buf != MAP_FAILED);
close(fd);
// check that this is an elf file
assert(size >= sizeof(Elf64_Ehdr));
const Elf64_Ehdr* eh64 = (const Elf64_Ehdr*)buf;
assert(IS_ELF32(*eh64) || IS_ELF64(*eh64) && "This file is not a valid ELF file");
#define LOAD_ELF(ehdr_t, phdr_t, shdr_t, sym_t) do { \
ehdr_t* eh = (ehdr_t*)buf; \
phdr_t* ph = (phdr_t*)(buf + eh->e_phoff); \
assert(size >= eh->e_phoff + eh->e_phnum*sizeof(*ph)); \
for (unsigned i = 0; i < eh->e_phnum; i++) { \
if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) { \
if (ph[i].p_filesz) { \
assert(size >= ph[i].p_offset + ph[i].p_filesz); \
} \
} \
} \
shdr_t* sh = (shdr_t*)(buf + eh->e_shoff); \
assert(size >= eh->e_shoff + eh->e_shnum*sizeof(*sh)); \
assert(eh->e_shstrndx < eh->e_shnum); \
assert(size >= sh[eh->e_shstrndx].sh_offset + sh[eh->e_shstrndx].sh_size); \
char *shstrtab = buf + sh[eh->e_shstrndx].sh_offset; \
unsigned strtabidx = 0, symtabidx = 0; \
for (unsigned i = 0; i < eh->e_shnum; i++) { \
unsigned max_len = sh[eh->e_shstrndx].sh_size - sh[i].sh_name; \
assert(sh[i].sh_name < sh[eh->e_shstrndx].sh_size); \
assert(strnlen(shstrtab + sh[i].sh_name, max_len) < max_len); \
sections[shstrtab + sh[i].sh_name] = sh[i].sh_addr; \
section_length[shstrtab + sh[i].sh_name] = sh[i].sh_size; \
if (sh[i].sh_type & SHT_NOBITS) continue; \
assert(size >= sh[i].sh_offset + sh[i].sh_size); \
if (strcmp(shstrtab + sh[i].sh_name, ".strtab") == 0) \
strtabidx = i; \
if (strcmp(shstrtab + sh[i].sh_name, ".symtab") == 0) \
symtabidx = i; \
} \
if (strtabidx && symtabidx) { \
char* strtab = buf + sh[strtabidx].sh_offset; \
sym_t* sym = (sym_t*)(buf + sh[symtabidx].sh_offset); \
for (unsigned i = 0; i < sh[symtabidx].sh_size/sizeof(sym_t); i++) { \
unsigned max_len = sh[strtabidx].sh_size - sym[i].st_name; \
symbols[strtab + sym[i].st_name] = sym[i].st_value; \
assert(sym[i].st_name < sh[strtabidx].sh_size); \
assert(strnlen(strtab + sym[i].st_name, max_len) < max_len); \
} \
} \
} while(0)
if (IS_ELF32(*eh64))
LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym);
else
LOAD_ELF(Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Sym);
munmap(buf, size);
return &symbols;
}

View file

@ -1,161 +0,0 @@
/* MTI_DPI */
/*
* Copyright 2002-2017 Mentor Graphics Corporation.
*
* Note:
* This file is automatically generated.
* Please do not edit this file - you will lose your edits.
*
* Settings when this file was generated:
* PLATFORM = 'linux_x86_64'
*/
#ifndef INCLUDED_ELFDPI
#define INCLUDED_ELFDPI
#ifdef __cplusplus
#define DPI_LINK_DECL extern "C"
#else
#define DPI_LINK_DECL
#endif
#include "svdpi.h"
#ifndef MTI_INCLUDED_TYPEDEF_uvm_hdl_path_slice
#define MTI_INCLUDED_TYPEDEF_uvm_hdl_path_slice
typedef struct {
const char* path;
int offset;
int size;
} uvm_hdl_path_slice;
#endif
#ifndef MTI_INCLUDED_TYPEDEF_uvm_printer_row_info
#define MTI_INCLUDED_TYPEDEF_uvm_printer_row_info
typedef struct {
int level;
const char* name;
const char* type_name;
const char* size;
const char* val;
} uvm_printer_row_info;
#endif
#ifndef MTI_INCLUDED_TYPEDEF_uvm_reg_bus_op
#define MTI_INCLUDED_TYPEDEF_uvm_reg_bus_op
typedef struct {
int kind;
svBitVecVal addr[SV_PACKED_DATA_NELEMS(64)];
svBitVecVal data[SV_PACKED_DATA_NELEMS(64)];
int n_bits;
svBitVecVal byte_en[SV_PACKED_DATA_NELEMS(8)];
int status;
} uvm_reg_bus_op;
#endif
DPI_LINK_DECL DPI_DLLESPEC
uint64_t
get_section_address(
const char* symb);
DPI_LINK_DECL DPI_DLLESPEC
uint64_t
get_section_size(
const char* symb);
DPI_LINK_DECL DPI_DLLESPEC
uint64_t
get_symbol_address(
const char* symb);
DPI_LINK_DECL DPI_DLLESPEC
void*
read_elf(
const char* fn);
DPI_LINK_DECL DPI_DLLESPEC
const char*
uvm_dpi_get_next_arg_c();
DPI_LINK_DECL DPI_DLLESPEC
const char*
uvm_dpi_get_tool_name_c();
DPI_LINK_DECL DPI_DLLESPEC
const char*
uvm_dpi_get_tool_version_c();
DPI_LINK_DECL DPI_DLLESPEC
void*
uvm_dpi_regcomp(
const char* regex);
DPI_LINK_DECL DPI_DLLESPEC
int
uvm_dpi_regexec(
void* preg,
const char* str);
DPI_LINK_DECL DPI_DLLESPEC
void
uvm_dpi_regfree(
void* preg);
DPI_LINK_DECL DPI_DLLESPEC
void
uvm_dump_re_cache();
DPI_LINK_DECL DPI_DLLESPEC
const char*
uvm_glob_to_re(
const char* glob);
DPI_LINK_DECL DPI_DLLESPEC
int
uvm_hdl_check_path(
const char* path);
DPI_LINK_DECL DPI_DLLESPEC
int
uvm_hdl_deposit(
const char* path,
const svLogicVecVal* value);
DPI_LINK_DECL DPI_DLLESPEC
int
uvm_hdl_force(
const char* path,
const svLogicVecVal* value);
DPI_LINK_DECL DPI_DLLESPEC
int
uvm_hdl_read(
const char* path,
svLogicVecVal* value);
DPI_LINK_DECL DPI_DLLESPEC
int
uvm_hdl_release(
const char* path);
DPI_LINK_DECL DPI_DLLESPEC
int
uvm_hdl_release_and_read(
const char* path,
svLogicVecVal* value);
DPI_LINK_DECL DPI_DLLESPEC
int
uvm_re_match(
const char* re,
const char* str);
#endif

View file

@ -1,51 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/21/2016
// Description: Instruction cache main verification environment
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class alu_env extends uvm_env;
// UVM Factory Registration Macro
`uvm_component_utils(alu_env)
//------------------------------------------
// Data Members
//------------------------------------------
fu_if_agent m_fu_if_agent;
fu_if_sequencer m_fu_if_sequencer;
alu_env_config m_cfg;
alu_scoreboard m_scoreboard;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "alu_env", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(alu_env_config)::get(this, "", "alu_env_config", m_cfg))
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration alu_env_config from uvm_config_db. Have you set() it?")
// Conditional instantiation goes here
// Create agent configuration
uvm_config_db #(fu_if_agent_config)::set(this, "m_fu_if_agent*",
"fu_if_agent_config",
m_cfg.m_fu_if_agent_config);
m_fu_if_agent = fu_if_agent::type_id::create("m_fu_if_agent", this);
// Get sequencer
m_fu_if_sequencer = fu_if_sequencer::type_id::create("m_fu_if_sequencer", this);
// create scoreboard
m_scoreboard = alu_scoreboard::type_id::create("m_scoreboard", this);
endfunction:build_phase
function void connect_phase(uvm_phase phase);
m_fu_if_sequencer = m_fu_if_agent.m_sequencer;
m_fu_if_agent.m_monitor.ap.connect(m_scoreboard.item_export);
endfunction: connect_phase
endclass : alu_env

View file

@ -1,19 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/20/2016
// Description: Configuration file for the pure instruction cache environment
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class alu_env_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(alu_env_config)
// a functional unit master interface
virtual fu_if m_fu_if;
// an agent config
fu_if_agent_config m_fu_if_agent_config;
endclass : alu_env_config

View file

@ -1,19 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 12/20/2016
// Description: Contains the environment for pure alu verification (functional unit interface)
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
package alu_env_pkg;
// Standard UVM import & include:
import uvm_pkg::*;
`include "uvm_macros.svh"
// Testbench related imports
import fu_if_agent_pkg::*;
import ariane_pkg::*;
// Includes for the config for the environment
`include "alu_env_config.svh"
`include "alu_scoreboard.svh"
// Includes the environment
`include "alu_env.svh"
endpackage

View file

@ -1,74 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 09/04/2017
// Description: ALU scoreboard, checks stimuli it receives from
// the monitors export
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class alu_scoreboard extends uvm_scoreboard;
`uvm_component_utils(alu_scoreboard);
uvm_analysis_imp#(fu_if_seq_item, alu_scoreboard) item_export;
bit [63:0] result;
bit [31:0] result32;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
item_export = new("item_export", this);
endfunction : build_phase
virtual function void write (fu_if_seq_item seq_item);
result = 64'b0;
result32 = 32'b0;
// check for all possible ALU operations
case(fu_op'(seq_item.operator))
ADD:
result = seq_item.operand_a + seq_item.operand_b;
ADDW: begin
result32 = seq_item.operand_a[31:0] + seq_item.operand_b[31:0];
result = {{32{result32[31]}}, result32}; // sign extend the result
end
SUB:
result = seq_item.operand_a - seq_item.operand_b;
SUBW: begin
result32 = seq_item.operand_a[31:0] - seq_item.operand_b[31:0];
result = {{32{result32[31]}}, result32};
end
XORL:
result = seq_item.operand_a ^ seq_item.operand_b;
ORL:
result = seq_item.operand_a | seq_item.operand_b;
ANDL:
result = seq_item.operand_a & seq_item.operand_b;
SRA:
result = $signed(seq_item.operand_a[63:0]) >>> seq_item.operand_b[5:0];
SRL:
result = $unsigned(seq_item.operand_a) >>> seq_item.operand_b[5:0];
SLL:
result = $unsigned(seq_item.operand_a) <<< seq_item.operand_b[5:0];
SRLW: begin
result32 = $unsigned(seq_item.operand_a[31:0]) >>> seq_item.operand_b[4:0];
result = {{32{result32[31]}}, result32};
end
SLLW: begin
result32 = $unsigned(seq_item.operand_a[31:0]) <<< seq_item.operand_b[4:0];
result = {{32{result32[31]}}, result32};
end
SRAW: begin
result32 = $signed(seq_item.operand_a[31:0]) >>> seq_item.operand_b[4:0];
result = {{32{result32[31]}}, result32};
end
endcase
if (result != seq_item.result)
`uvm_error("ALU Scoreboard", $sformatf("Result: %0h, Expected %0h", seq_item.result, result))
endfunction : write;
endclass : alu_scoreboard

View file

@ -1,73 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: Environment which instantiates the agent and all environment
// related components such as a scoreboard etc.
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class core_env extends uvm_env;
// UVM Factory Registration Macro
`uvm_component_utils(core_env)
//------------------------------------------
// Data Members
//------------------------------------------
core_if_agent m_core_if_agent;
dcache_if_agent m_dcache_if_agent;
core_if_sequencer m_core_if_sequencer;
core_env_config m_cfg;
core_eoc m_eoc;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "core_env", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(core_env_config)::get(this, "", "core_env_config", m_cfg))
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration core_env_config from uvm_config_db. Have you set() it?")
// Conditional instantiation goes here
// Create agent configuration
uvm_config_db #(core_if_agent_config)::set(this, "m_core_if_agent*",
"core_if_agent_config",
m_cfg.m_core_if_agent_config);
m_core_if_agent = core_if_agent::type_id::create("m_core_if_agent", this);
uvm_config_db #(core_if_agent_config)::set(this, "m_core_if_agent*",
"core_if_agent_config",
m_cfg.m_core_if_agent_config);
// get instruction memory interface
m_dcache_if_agent = dcache_if_agent::type_id::create("m_dcache_if_agent", this);
uvm_config_db #(dcache_if_agent_config)::set(this, "m_dcache_if_agent*",
"dcache_if_agent_config",
m_cfg.m_dcache_if_agent_config);
// Get sequencer
m_core_if_sequencer = core_if_sequencer::type_id::create("m_core_if_sequencer", this);
m_eoc = core_eoc::type_id::create("m_eoc", this);
endfunction:build_phase
function void connect_phase(uvm_phase phase);
m_core_if_sequencer = m_core_if_agent.m_sequencer;
m_dcache_if_agent.m_monitor.m_ap.connect(m_eoc.item_export);
endfunction: connect_phase
endclass : core_env

View file

@ -1,31 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: core configuration object
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class core_env_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(core_env_config)
// a functional unit master interface
virtual core_if m_core_if;
virtual dcache_if m_dcache_if;
// an agent config
core_if_agent_config m_core_if_agent_config;
dcache_if_agent_config m_dcache_if_agent_config;
endclass : core_env_config

View file

@ -1,28 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: core package
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
package core_env_pkg;
// Standard UVM import & include:
import uvm_pkg::*;
`include "uvm_macros.svh"
// Testbench related imports
import core_if_agent_pkg::*;
import dcache_if_agent_pkg::*;
`include "core_eoc.svh"
// Includes for the config for the environment
`include "core_env_config.svh"
// Includes the environment
`include "core_env.svh"
endpackage

View file

@ -1,98 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 05.06.2017
// Description: Determines end of computation
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class core_eoc extends uvm_component;
// UVM Factory Registration Macro
`uvm_component_utils(core_eoc)
longint unsigned tohost;
longint unsigned begin_signature;
logic got_write = 1'b0;
int exit_code = 0;
int f;
string sig_dump_name;
string base_dir;
// get the command line processor for parsing the plus args
static uvm_cmdline_processor uvcl = uvm_cmdline_processor::get_inst();
//------------------------------------------
// Methods
//------------------------------------------
// analysis port
uvm_analysis_imp #(dcache_if_seq_item, core_eoc) item_export;
// Standard UVM Methods:
function new(string name = "core_eoc", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// get the signature dump file name
void'(uvcl.get_arg_value("+BASEDIR=", base_dir));
// check if the argument was supplied
if(uvcl.get_arg_value("+signature=", sig_dump_name) == 0) begin
sig_dump_name = "test.ariane.sig";
end
sig_dump_name = {base_dir, "/", sig_dump_name};
if (!uvm_config_db #(longint unsigned)::get(this, "", "tohost", tohost))
`uvm_fatal("VIF CONFIG", "Cannot get() interface core_if from uvm_config_db. Have you set() it?")
if (!uvm_config_db #(longint unsigned)::get(this, "", "begin_signature", begin_signature))
`uvm_fatal("VIF CONFIG", "Cannot get() interface core_if from uvm_config_db. Have you set() it?")
// create the analysis export
item_export = new("item_export", this);
endfunction
function void write (dcache_if_seq_item seq_item);
// get the tohost value -> for details see the riscv-fesvr implementation
if (seq_item.address == tohost) begin
exit_code = seq_item.wdata >> 1;
if (exit_code)
`uvm_error( "Core Test", $sformatf("*** FAILED *** (tohost = %0d)", exit_code) )
else
`uvm_info( "Core Test", $sformatf("*** SUCCESS *** (tohost = %0d)", exit_code), UVM_LOW)
got_write = 1'b1;
end
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this, "core_eoc");
super.run_phase(phase);
wait (got_write);
phase.drop_objection(this, "core_eoc");
endtask
virtual function void extract_phase( uvm_phase phase );
super.extract_phase(phase);
// Dump Signature
if (this.begin_signature != '0) begin
this.f = $fopen(sig_dump_name, "w");
// extract 256 byte register dump + 1024 byte memory dump starting from begin_signature symbol
for (int i = this.begin_signature; i < this.begin_signature + 162; i += 2)
$fwrite(this.f, "%x%x\n", $root.core_tb.core_mem_i.ram_i.mem[i + 1], $root.core_tb.core_mem_i.ram_i.mem[i]);
$fclose(this.f);
end
endfunction
endclass : core_eoc

View file

@ -1,63 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: Environment which instantiates the agent and all environment
// related components such as a scoreboard etc.
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class lsu_env extends uvm_env;
// UVM Factory Registration Macro
`uvm_component_utils(lsu_env)
//------------------------------------------
// Data Members
//------------------------------------------
mem_if_agent m_mem_if_agent;
lsu_if_agent m_lsu_if_agent;
lsu_if_sequencer m_lsu_if_sequencer;
lsu_env_config m_cfg;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "lsu_env", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(lsu_env_config)::get(this, "", "lsu_env_config", m_cfg))
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration lsu_env_config from uvm_config_db. Have you set() it?")
// Conditional instantiation goes here
// Create mem_if agent configuration
uvm_config_db #(mem_if_agent_config)::set(this, "m_mem_if_agent*",
"mem_if_agent_config",
m_cfg.m_mem_if_agent_config);
m_mem_if_agent = mem_if_agent::type_id::create("m_mem_if_agent", this);
// Create lsu_if agent configuration
uvm_config_db #(lsu_if_agent_config)::set(this, "m_lsu_if_agent*",
"lsu_if_agent_config",
m_cfg.m_lsu_if_agent_config);
m_lsu_if_agent = lsu_if_agent::type_id::create("m_lsu_if_agent", this);
// Get sequencer
m_lsu_if_sequencer = lsu_if_sequencer::type_id::create("m_lsu_if_sequencer", this);
endfunction:build_phase
function void connect_phase(uvm_phase phase);
m_lsu_if_sequencer = m_lsu_if_agent.m_sequencer;
endfunction: connect_phase
endclass : lsu_env

View file

@ -1,30 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: lsu configuration object
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class lsu_env_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(lsu_env_config)
// a functional unit master interface
virtual mem_if m_mem_if;
virtual lsu_if m_lsu_if;
// an agent config
mem_if_agent_config m_mem_if_agent_config;
lsu_if_agent_config m_lsu_if_agent_config;
endclass : lsu_env_config

View file

@ -1,27 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: lsu package
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
package lsu_env_pkg;
// Standard UVM import & include:
import uvm_pkg::*;
`include "uvm_macros.svh"
// Testbench related imports
import mem_if_agent_pkg::*;
import lsu_if_agent_pkg::*;
// Includes for the config for the environment
`include "lsu_env_config.svh"
// Includes the environment
`include "lsu_env.svh"
endpackage

View file

@ -1,77 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 30.04.2017
// Description: Environment which instantiates the agent and all environment
// related components such as a scoreboard etc.
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class mem_arbiter_env extends uvm_env;
// UVM Factory Registration Macro
`uvm_component_utils(mem_arbiter_env)
//------------------------------------------
// Data Members
//------------------------------------------
dcache_if_agent m_dcache_if_slave_agent;
dcache_if_agent m_dcache_if_master_agents[3];
dcache_if_sequencer m_dcache_if_sequencers[3];
mem_arbiter_env_config m_cfg;
mem_arbiter_scoreboard m_scoreboard;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "mem_arbiter_env", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(mem_arbiter_env_config)::get(this, "", "mem_arbiter_env_config", m_cfg))
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration mem_arbiter_env_config from uvm_config_db. Have you set() it?")
// Conditional instantiation goes here
// Create agent configurations
uvm_config_db #(dcache_if_agent_config)::set(this, "m_dcache_if_slave*",
"dcache_if_agent_config",
m_cfg.m_dcache_if_slave_agent);
m_dcache_if_slave_agent = dcache_if_agent::type_id::create("m_dcache_if_slave_agent", this);
// create 3 master memory interfaces
for (int i = 0; i < 3; i++) begin
uvm_config_db #(dcache_if_agent_config)::set(this, {"m_dcache_if_master", i, "*"},
"dcache_if_agent_config",
m_cfg.m_dcache_if_master_agents[i]);
m_dcache_if_master_agents[i] = dcache_if_agent::type_id::create({"m_dcache_if_master", i, "_agent"}, this);
// Get 3 sequencers
m_dcache_if_sequencers[i] = dcache_if_sequencer::type_id::create({"m_dcache_if_sequencer", i}, this);
end
// instantiate the scoreboard
m_scoreboard = mem_arbiter_scoreboard::type_id::create("m_scoreboard", this);
endfunction:build_phase
function void connect_phase(uvm_phase phase);
// connect the sequencers and monitor to the master agents
for (int i = 0; i < 3; i++) begin
m_dcache_if_sequencers[i] = m_dcache_if_master_agents[i].m_sequencer;
m_dcache_if_master_agents[i].m_monitor.m_ap.connect(m_scoreboard.item_export);
end
// connect the slave monitor to the scoreboard
m_dcache_if_slave_agent.m_monitor.m_ap.connect(m_scoreboard.item_export);
endfunction: connect_phase
endclass : mem_arbiter_env

View file

@ -1,29 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 30.04.2017
// Description: mem_arbiter configuration object
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class mem_arbiter_env_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(mem_arbiter_env_config)
// a functional unit master interface
virtual dcache_if m_dcache_if_slave;
virtual dcache_if m_dcache_if_masters[3];
// an agent config
dcache_if_agent_config m_dcache_if_slave_agent;
dcache_if_agent_config m_dcache_if_master_agents[3];
endclass : mem_arbiter_env_config

View file

@ -1,29 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 30.04.2017
// Description: mem_arbiter package
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
package mem_arbiter_env_pkg;
// Standard UVM import & include:
import uvm_pkg::*;
`include "uvm_macros.svh"
// Testbench related imports
import dcache_if_agent_pkg::*;
// Include the scoreboard
`include "mem_arbiter_scoreboard.svh"
// Includes for the config for the environment
`include "mem_arbiter_env_config.svh"
// Includes the environment
`include "mem_arbiter_env.svh"
endpackage

View file

@ -1,60 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 01.05.2017
// Description: Memory Arbiter scoreboard
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class mem_arbiter_scoreboard extends uvm_scoreboard;
`uvm_component_utils(mem_arbiter_scoreboard);
int slave_answer_cnt, master_answer_cnt;
uvm_analysis_imp #(dcache_if_seq_item, mem_arbiter_scoreboard) item_export;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
item_export = new("item_slave_export", this);
slave_answer_cnt = 0;
master_answer_cnt = 0;
endfunction : build_phase
virtual function void write (dcache_if_seq_item seq_item);
// $display("%s", seq_item.convert2string());
// the answer is from a master
// the address and data should be the same when we use the replay system
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
slave_answer_cnt++;
end
endfunction
// check here for the total amount of transactions
virtual function void extract_phase( uvm_phase phase );
super.extract_phase(phase);
if (master_answer_cnt !== slave_answer_cnt) begin
`uvm_error("DCache Arbiter Scoreboard", $sformatf("Mismatch in overall result count. Expected: %d Got: %d", slave_answer_cnt, master_answer_cnt))
end else
`uvm_info("DCache Arbiter Scoreboard", $sformatf("Overall result count: Expected: %d Got: %d", slave_answer_cnt, master_answer_cnt), UVM_LOW)
endfunction : extract_phase
endclass : mem_arbiter_scoreboard

View file

@ -1,72 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: Environment which instantiates the agent and all environment
// related components such as a scoreboard etc.
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class store_queue_env extends uvm_env;
// UVM Factory Registration Macro
`uvm_component_utils(store_queue_env)
//------------------------------------------
// Data Members
//------------------------------------------
// agents
store_queue_if_agent m_store_queue_if_agent;
dcache_if_agent m_dcache_if_agent;
store_queue_if_sequencer m_store_queue_if_sequencer;
store_queue_env_config m_cfg;
store_queue_scoreboard m_scoreboard;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "store_queue_env", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
if (!uvm_config_db #(store_queue_env_config)::get(this, "", "store_queue_env_config", m_cfg))
`uvm_fatal("CONFIG_LOAD", "Cannot get() configuration store_queue_env_config from uvm_config_db. Have you set() it?")
// Conditional instantiation goes here
// Create agent configuration
// Store Queue IF
uvm_config_db #(store_queue_if_agent_config)::set(this, "m_store_queue_if_agent*",
"store_queue_if_agent_config",
m_cfg.m_store_queue_if_agent_config);
m_store_queue_if_agent = store_queue_if_agent::type_id::create("m_store_queue_if_agent", this);
// DCache IF
uvm_config_db #(dcache_if_agent_config)::set(this, "m_dcache_if_agent*",
"dcache_if_agent_config",
m_cfg.m_dcache_if_agent_config);
m_dcache_if_agent = dcache_if_agent::type_id::create("m_dcache_if_agent", this);
// Get sequencer
m_store_queue_if_sequencer = store_queue_if_sequencer::type_id::create("m_store_queue_if_sequencer", this);
// instantiate scoreboard
m_scoreboard = store_queue_scoreboard::type_id::create("m_scoreboard", this);
endfunction:build_phase
function void connect_phase(uvm_phase phase);
m_store_queue_if_sequencer = m_store_queue_if_agent.m_sequencer;
m_store_queue_if_agent.m_monitor.m_ap.connect(m_scoreboard.store_queue_item_export);
m_dcache_if_agent.m_monitor.m_ap.connect(m_scoreboard.dcache_item_export);
endfunction: connect_phase
endclass : store_queue_env

View file

@ -1,29 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: store_queue configuration object
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class store_queue_env_config extends uvm_object;
// UVM Factory Registration Macro
`uvm_object_utils(store_queue_env_config)
// a store queue master interface
virtual store_queue_if m_store_queue_if;
virtual dcache_if m_dcache_if;
// an agent config
store_queue_if_agent_config m_store_queue_if_agent_config;
dcache_if_agent_config m_dcache_if_agent_config;
endclass : store_queue_env_config

View file

@ -1,29 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: store_queue package
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
package store_queue_env_pkg;
// Standard UVM import & include:
import uvm_pkg::*;
`include "uvm_macros.svh"
// Testbench related imports
import store_queue_if_agent_pkg::*;
import dcache_if_agent_pkg::*;
// Include scoreboard
`include "store_queue_scoreboard.svh"
// Includes for the config for the environment
`include "store_queue_env_config.svh"
// Includes the environment
`include "store_queue_env.svh"
endpackage

View file

@ -1,67 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 29.05.2017
// Description: Store Queue scoreboard
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
class store_queue_scoreboard extends uvm_scoreboard;
`uvm_component_utils(store_queue_scoreboard);
uvm_analysis_imp #(store_queue_if_seq_item, store_queue_scoreboard) store_queue_item_export;
uvm_analysis_imp #(dcache_if_seq_item, store_queue_scoreboard) dcache_item_export;
store_queue_if_seq_item store_queue_items [$];
function new(string name, uvm_component parent);
super.new(name, parent);
store_queue_item_export = new("store_queue_item_export", this);
dcache_item_export = new("dcache_item_export", this);
endfunction : new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction : build_phase
virtual function void write (uvm_sequence_item seq_item);
// variables to hold the casts
store_queue_if_seq_item casted_store_queue = new;
store_queue_if_seq_item store_queue_item;
dcache_if_seq_item casted_dcache = new;
// got a store queue item
if (seq_item.get_type_name() == "store_queue_if_seq_item") begin
// $display("%s", seq_item.convert2string());
$cast(casted_store_queue, seq_item.clone());
// this is the first item which is coming, so put it in a queue
store_queue_items.push_back(casted_store_queue);
end
// got an dcache item
if (seq_item.get_type_name() == "dcache_if_seq_item") begin
// cast dcache variable
$cast(casted_dcache, seq_item.clone());
// get the latest store queue item
store_queue_item = store_queue_items.pop_front();
// match it with the expected result from the store queue side
if (store_queue_item.address != casted_dcache.address ||
store_queue_item.data != casted_dcache.wdata ||
store_queue_item.be != casted_dcache.be) begin
`uvm_error("Store Queue Scoreboard", $sformatf("Mismatch. Expected: %s Got: %s", store_queue_item.convert2string(), casted_dcache.convert2string()));
end
end
endfunction
endclass : store_queue_scoreboard

View file

@ -1,96 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 14.5.2017
// Description: Fetch FIFO testbench
//
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
import ariane_pkg::*;
import fetch_fifo_pkg::*;
module fetch_fifo_tb;
logic rst_ni, clk_i;
fetch_fifo_if fetch_fifo_if (clk_i);
fetch_fifo
dut (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( fetch_fifo_if.flush ),
.branch_predict_i ( fetch_fifo_if.in_branch_predict ),
.in_addr_i ( fetch_fifo_if.in_addr ),
.in_rdata_i ( fetch_fifo_if.in_rdata ),
.in_valid_i ( fetch_fifo_if.in_valid ),
.in_ready_o ( fetch_fifo_if.in_ready ),
.fetch_entry_o ( fetch_fifo_if.fetch_entry ),
.out_valid_o ( fetch_fifo_if.out_valid ),
.out_ready_i ( fetch_fifo_if.out_ready )
);
initial begin
clk_i = 1'b0;
rst_ni = 1'b0;
repeat(8)
#10ns clk_i = ~clk_i;
rst_ni = 1'b1;
forever
#10ns clk_i = ~clk_i;
end
// simulator stopper, this is suboptimal better go for coverage
initial begin
#10000000ns
$finish;
end
program testbench (fetch_fifo_if fetch_fifo_if);
instruction_stream is = new;
fetch_fifo_model model = new;
instruction_queue_entry_t iqe;
initial begin
fetch_fifo_if.mck.flush <= 1'b0;
fetch_fifo_if.mck.in_branch_predict <= 'b0;
fetch_fifo_if.mck.in_addr <= 'b0;
fetch_fifo_if.mck.in_rdata <= 'b0;
fetch_fifo_if.mck.in_valid <= 'b0;
fetch_fifo_if.mck.out_ready <= 'b0;
wait(rst_ni == 1'b1);
// Driver
forever begin
@(fetch_fifo_if.mck iff fetch_fifo_if.in_ready);
do begin
iqe = is.get_instruction();
fetch_fifo_if.mck.in_addr <= iqe.address;
fetch_fifo_if.mck.in_rdata <= iqe.instr;
fetch_fifo_if.mck.in_branch_predict <= iqe.bp;
fetch_fifo_if.mck.in_valid <= 1'b1;
@(fetch_fifo_if.mck);
end while (fetch_fifo_if.mck.in_ready);
fetch_fifo_if.mck.in_valid <= 1'b0;
end
end
endprogram
testbench tb(fetch_fifo_if);
endmodule

View file

@ -1,127 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 24.4.2017
// Description: FIFO testbench
//
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
module fifo_tb;
logic rst_ni, clk;
fifo_if #(.dtype ( logic[7:0] )) fifo_if (clk);
logic push, pop;
assign fifo_if.push = ~fifo_if.full & push;
assign fifo_if.pop = ~fifo_if.empty & pop;
fifo
#(.dtype ( logic[7:0] ))
dut
(
.clk_i ( clk ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.full_o ( fifo_if.full ),
.empty_o ( fifo_if.empty ),
.single_element_o ( ),
.data_i ( fifo_if.wdata ),
.push_i ( fifo_if.push ),
.data_o ( fifo_if.rdata ),
.pop_i ( fifo_if.pop )
);
initial begin
clk = 1'b0;
rst_ni = 1'b0;
repeat(8)
#10ns clk = ~clk;
rst_ni = 1'b1;
forever
#10ns clk = ~clk;
end
// simulator stopper, this is suboptimal better go for coverage
initial begin
#10000000ns
$stop;
end
program testbench (fifo_if fifo_if, output logic push, output logic pop);
logic[7:0] queue [$];
// ----------
// Driver
// ----------
initial begin
fifo_if.mck.wdata <= $urandom_range(0,256);
push <= 1'b0;
// wait for reset to be high
wait(rst_ni == 1'b1);
// push
forever begin
repeat($urandom_range(0, 8)) @(fifo_if.mck)
// if there is space lets push some random data
if (~fifo_if.mck.full) begin
fifo_if.mck.wdata <= $urandom_range(0,256);
push <= 1'b1;
end else begin
fifo_if.mck.wdata <= $urandom_range(0,256);
push <= 1'b0;
end
end
end
initial begin
// wait for reset to be high
wait(rst_ni == 1'b1);
// pop from queue
forever begin
@(fifo_if.mck)
pop <= 1'b1;
repeat($urandom_range(0, 8)) @(fifo_if.mck)
pop <= 1'b0;
end
end
// -------------------
// Monitor && Checker
// -------------------
initial begin
automatic logic [7:0] data;
forever begin
@(fifo_if.pck)
if (fifo_if.pck.push) begin
queue.push_back(fifo_if.pck.wdata);
end
if (fifo_if.pck.pop) begin
data = queue.pop_front();
// $display("Time: %t, Expected: %0h Got %0h", $time, data, fifo_if.pck.rdata);
assert(data == fifo_if.pck.rdata) else $error("Mismatch, Expected: %0h Got %0h", data, fifo_if.pck.rdata);
end
end
end
endprogram
testbench tb(fifo_if, push, pop);
endmodule

View file

@ -1,109 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 02.05.2017
// Description: LSU Testbench
//
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
module lsu_tb;
import uvm_pkg::*;
// import the main test class
import lsu_lib_pkg::*;
import ariane_pkg::*;
logic rst_ni, clk;
mem_if slave(clk);
mem_if instr_if(clk);
lsu_if lsu(clk);
lsu dut (
.clk_i ( clk ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.operator_i ( lsu.operator ),
.operand_a_i ( lsu.operand_a ),
.operand_b_i ( lsu.operand_b ),
.imm_i ( lsu.imm ),
.lsu_ready_o ( lsu.ready ),
.lsu_valid_i ( lsu.source_valid ),
.trans_id_i ( lsu.lsu_trans_id_id ),
.lsu_trans_id_o ( lsu.lsu_trans_id_wb ),
.lsu_result_o ( lsu.result ),
.lsu_valid_o ( lsu.result_valid ),
.commit_i ( lsu.commit ),
// we are currently no testing the PTW and MMU
.enable_translation_i ( 1'b0 ),
.fetch_req_i ( 1'b0 ),
.fetch_gnt_o ( ),
.fetch_valid_o ( ),
.fetch_err_o ( ),
.fetch_vaddr_i ( 64'b0 ),
.fetch_rdata_o ( ),
.priv_lvl_i ( PRIV_LVL_M ),
.flag_pum_i ( 1'b0 ),
.flag_mxr_i ( 1'b0 ),
.pd_ppn_i ( 38'b0 ),
.asid_i ( 1'b0 ),
.flush_tlb_i ( 1'b0 ),
.instr_if_address_o ( instr_if.address ),
.instr_if_data_req_o ( instr_if.data_req ),
.instr_if_data_be_o ( instr_if.data_be[3:0] ),
.instr_if_data_gnt_i ( instr_if.data_gnt ),
.instr_if_data_rvalid_i ( instr_if.data_rvalid ),
.instr_if_data_rdata_i ( instr_if.data_rdata[31:0] ),
.data_if_address_index_o ( slave.address ),
.data_if_data_wdata_o ( slave.data_wdata ),
.data_if_data_req_o ( slave.data_req ),
.data_if_data_we_o ( slave.data_we ),
.data_if_data_be_o ( slave.data_be ),
// hack to not get a grant without a request
.data_if_data_gnt_i ( slave.data_req & slave.data_gnt ),
.data_if_data_rvalid_i ( slave.data_rvalid ),
.data_if_data_rdata_i ( slave.data_rdata ),
.lsu_exception_o ( lsu.exception )
);
initial begin
clk = 1'b0;
rst_ni = 1'b0;
repeat(8)
#10ns clk = ~clk;
rst_ni = 1'b1;
forever
#10ns clk = ~clk;
end
program testbench (mem_if slave, lsu_if lsu);
initial begin
// register the memory interface
uvm_config_db #(virtual mem_if)::set(null, "uvm_test_top", "mem_if", slave);
uvm_config_db #(virtual lsu_if)::set(null, "uvm_test_top", "lsu_if", lsu);
// print the topology
uvm_top.enable_print_topology = 1;
// Start UVM test
run_test();
end
endprogram
testbench tb (slave, lsu);
endmodule

View file

@ -1,59 +0,0 @@
class Scoreboard;
scoreboard_entry decoded_instructions[$];
scoreboard_entry issued_instructions[$];
static logic[TRANS_ID_BITS-1:0] i = 0;
// utility function to get randomized input data
static function scoreboard_entry randomize_scoreboard();
exception exception = { 63'h0, 63'h0, 1'b0};
scoreboard_entry entry = {
63'b0, i, ALU, ADD, 5'h5, 5'h5, 5'h5, 64'h0, 1'b0, 1'b0, exception, 1'b0
};
return entry;
endfunction : randomize_scoreboard
// just allow one operation
function void submit_instruction(scoreboard_entry entry);
entry.trans_id = i;
i = (++i % 8);
decoded_instructions.push_back(entry);
endfunction : submit_instruction
// get the current issue instruction
function scoreboard_entry get_issue();
scoreboard_entry issue = decoded_instructions.pop_front();
// put in issue queue
issued_instructions.push_back(issue);
return issue;
endfunction : get_issue
// write back to scoreboard
function void write_back(logic [TRANS_ID_BITS-1:0] trans_id, logic [63:0] value);
for (int i = 0; i < $size(issued_instructions); i++) begin
if (issued_instructions[i].trans_id == trans_id) begin
// $display("Model Write Back: %0h", value);
issued_instructions[i].valid = 1'b1;
issued_instructions[i].result = value;
end
end
endfunction : write_back
// commit the instruction, e.g.: delete it from the entries
function scoreboard_entry commit();
return issued_instructions.pop_front();
endfunction : commit
// return the clobbered registers
function logic [31:0][$bits(fu_t)-1:0] get_clobber();
logic [31:0][$bits(fu_t)-1:0] result;
for (int i = 0; i < $size(issued_instructions); i++) begin
if (issued_instructions[i].rd != 5'h0) begin
result[issued_instructions[i].rd] = issued_instructions[i].fu;
end
end
return result;
endfunction : get_clobber
endclass : Scoreboard

View file

@ -1,202 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 10/04/2017
// Description: Top level testbench module. Instantiates the top level DUT, configures
// the virtual interfaces and starts the test passed by +UVM_TEST+
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// TODO, test register read and clobber interface, make a proper TB out of it
import uvm_pkg::*;
import ariane_pkg::*;
module scoreboard_tb;
`include "models/scoreboard.sv"
logic rst_ni, clk;
scoreboard_if #(.NR_WB_PORTS(1) ) scoreboard_if (clk);
scoreboard #(
.NR_WB_PORTS ( 1 ),
.NR_ENTRIES ( NR_SB_ENTRIES )
)
dut
(
.clk_i ( clk ),
.rst_ni ( rst_ni ),
.flush_i ( scoreboard_if.flush ),
.rd_clobber_o ( scoreboard_if.rd_clobber ),
.rs1_i ( scoreboard_if.rs1_address ),
.rs1_o ( scoreboard_if.rs1 ),
.rs1_valid_o ( scoreboard_if.rs1_valid ),
.rs2_i ( scoreboard_if.rs2_address ),
.rs2_o ( scoreboard_if.rs2 ),
.rs2_valid_o ( scoreboard_if.rs2_valid ),
.commit_instr_o ( scoreboard_if.commit_instr ),
.commit_ack_i ( scoreboard_if.commit_ack ),
.decoded_instr_i ( scoreboard_if.decoded_instr ),
.decoded_instr_valid_i ( scoreboard_if.decoded_instr_valid ),
.decoded_instr_ack_o ( scoreboard_if.decoded_instr_ack ),
.issue_instr_o ( scoreboard_if.issue_instr ),
.issue_instr_valid_o ( scoreboard_if.issue_instr_valid ),
.issue_ack_i ( scoreboard_if.issue_ack ),
.trans_id_i ( scoreboard_if.trans_id ),
.wdata_i ( scoreboard_if.wdata ),
.ex_i ( scoreboard_if.ex ),
.wb_valid_i ( scoreboard_if.wb_valid )
);
initial begin
clk = 1'b0;
rst_ni = 1'b0;
repeat(8)
#10ns clk = ~clk;
rst_ni = 1'b1;
forever
#10ns clk = ~clk;
end
// simulator stopper, this is suboptimal better go for coverage
initial begin
#10000000ns
$stop;
end
program testbench (scoreboard_if scoreboard_if);
// variable declarations
Scoreboard sb = new;
semaphore wb_lock = new(1);
logic[4:0] i = 0;
assign scoreboard_if.flush = 1'b0;
initial begin
// register the scoreboard interface
// uvm_config_db #(virtual scoreboard_if)::set(null, "uvm_test_top", "scoreboard_vif", scoreboard_if);
end
// push new decoded instructions
initial begin
scoreboard_if.mck.decoded_instr_valid <= 1'b0;
wait(rst_ni == 1'b1);
// load the scoreboard until it is full
forever begin
@(scoreboard_if.mck);
// if we are not full load another instruction
scoreboard_if.mck.decoded_instr <= Scoreboard::randomize_scoreboard();
scoreboard_if.mck.decoded_instr_valid <= 1'b1;
@(scoreboard_if.mck iff scoreboard_if.mck.decoded_instr_ack == 1'b1)
scoreboard_if.mck.decoded_instr_valid <= 1'b0;
end
end
scoreboard_entry issue_instruction;
// pull e.g. issue instructions
initial begin
// reset values
scoreboard_if.mck.trans_id <= 'b0;
scoreboard_if.mck.wdata <= 'b0;
scoreboard_if.mck.wb_valid <= 1'b0;
wait(rst_ni == 1'b1);
forever begin
@(scoreboard_if.mck);
if (scoreboard_if.issue_instr_valid == 1'b1) begin
scoreboard_if.mck.issue_ack <= 1'b1;
issue_instruction <= scoreboard_if.mck.issue_instr;
// $display("Time: %t, Issuing: %0h, Valid: %h", $time, scoreboard_if.mck.issue_instr.pc, scoreboard_if.issue_instr_valid);
@(scoreboard_if.mck)
scoreboard_if.mck.issue_ack <= 1'b0;
// generate a delay between 0 and 3 cycles for WB, write-back out of order
fork
write_back: begin
automatic logic [TRANS_ID_BITS-1:0] trans_id = issue_instruction.trans_id;
automatic logic [63:0] random_data = $urandom_range(0, 2**31);
wb_lock.get(1);
repeat ($urandom_range(1,20)) @(scoreboard_if.mck);
// $display("Time: %t, Writing Back: %0h", $time, thread_copy.pc);
scoreboard_if.mck.trans_id <= trans_id;
scoreboard_if.mck.wdata <= random_data;
scoreboard_if.mck.wb_valid <= 1'b1;
// so far no exception testing
scoreboard_if.mck.ex <= '{default: 0};
// $display("Write Back: %0h", random_data);
sb.write_back(trans_id, random_data);
@(scoreboard_if.mck);
scoreboard_if.mck.wb_valid <= 1'b0;
wb_lock.put(1);
end
join_none
end else begin
scoreboard_if.mck.issue_ack <= 1'b0;
end
end
end
// commit instructions
initial begin
wait(rst_ni == 1'b1);
forever begin
repeat ($urandom_range(1,3)) @(scoreboard_if.mck);
if (scoreboard_if.mck.commit_instr.valid == 1'b1) begin
// $display("Time: %t, Commiting: %0h", $time, scoreboard_if.mck.commit_instr.pc);
scoreboard_if.mck.commit_ack <= 1'b1;
@(scoreboard_if.mck);
scoreboard_if.mck.commit_ack <= 1'b0;
repeat ($urandom_range(0,3)) @(scoreboard_if.mck);
end else
scoreboard_if.mck.commit_ack <= 1'b0;
end
end
// ------------------
// Monitor + Checker
// ------------------
initial begin
wait(rst_ni == 1'b1);
forever begin
@(scoreboard_if.pck);
if (scoreboard_if.pck.decoded_instr_valid == 1'b1) begin
sb.submit_instruction(scoreboard_if.pck.decoded_instr);
end
end
end
scoreboard_entry tmp_sbe;
initial begin
wait(rst_ni == 1'b1);
forever begin
@(scoreboard_if.pck);
if (scoreboard_if.pck.issue_instr_valid == 1'b1 && scoreboard_if.pck.issue_ack) begin
tmp_sbe = sb.get_issue();
assert (tmp_sbe.trans_id == issue_instruction.trans_id) else $error("Issue instruction mismatch. Expected: %p Got: %p", tmp_sbe, issue_instruction);
end
end
end
// commit checker
scoreboard_entry comp;
initial begin
wait(rst_ni == 1'b1);
forever begin
@(scoreboard_if.pck);
if (scoreboard_if.pck.commit_ack == 1'b1) begin
comp = sb.commit();
assert (comp === scoreboard_if.pck.commit_instr) else $error($sformatf("Mismatch: \nExpected: %p \nGot: %p", comp, scoreboard_if.pck.commit_instr));
end
end
end
endprogram
testbench tb(scoreboard_if);
endmodule

View file

@ -1,22 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 09/04/2017
// Description: Sequence specialization, extends basic sequence
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
class add_sequence extends basic_sequence;
`uvm_object_utils(add_sequence);
function new(string name = "add");
super.new(name);
endfunction : new
function fu_op get_operator();
return ADD;
endfunction : get_operator
task body();
super.body();
endtask : body
endclass : add_sequence

Some files were not shown because too many files have changed in this diff Show more