Add LSU interface

This commit is contained in:
Florian Zaruba 2017-05-02 12:35:29 +02:00
parent 3019168ddb
commit 41832a18d9
10 changed files with 499 additions and 27 deletions

View file

@ -0,0 +1,57 @@
// 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
exception exception;
// FU interface configured as master
clocking mck @(posedge clk);
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);
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

@ -0,0 +1,57 @@
// 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

@ -0,0 +1,37 @@
// 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 fu;
//------------------------------------------
// 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

@ -0,0 +1,37 @@
// 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::*;
`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

@ -0,0 +1,47 @@
// 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 fu;
//---------------------
// 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);
lsu_if_seq_item cmd;
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 #(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?")
fu = m_cfg.fu;
endfunction: build_phase
endclass : lsu_if_driver

View file

@ -0,0 +1,62 @@
// 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 fu;
//---------------------
// 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
fu = m_cfg.fu;
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

@ -0,0 +1,89 @@
// 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)
//------------------------------------------
// TODO: set data members
//------------------------------------------
// 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:
// e.g.:
// operator = rhs_.operator;
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); // && 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 : lsu_if_seq_item

View file

@ -0,0 +1,53 @@
// 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

@ -0,0 +1,29 @@
// 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

@ -29,38 +29,41 @@ module lsu_tb;
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 ( ),
.operand_a_i ( ),
.operand_b_i ( ),
.imm_i ( ),
.lsu_ready_o ( ),
.lsu_valid_i ( ),
.lsu_trans_id_i ( ),
.lsu_trans_id_o ( ),
.lsu_result_o ( ),
.lsu_valid_o ( ),
.commit_i ( ),
.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 ),
.lsu_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 ( ),
.fetch_req_i ( 1'b0 ),
.fetch_gnt_o ( ),
.fetch_valid_o ( ),
.fetch_err_o ( ),
.fetch_vaddr_i ( ),
.fetch_vaddr_i ( 64'b0 ),
.fetch_rdata_o ( ),
.priv_lvl_i ( ),
.flag_pum_i ( ),
.flag_mxr_i ( ),
.pd_ppn_i ( ),
.asid_i ( ),
.flush_tlb_i ( ),
.instr_if ( instr_if ),
.data_if ( slave ),
.lsu_exception_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 ( instr_if ),
.data_if ( slave ),
.lsu_exception_o ( lsu.exception )
);
initial begin
@ -74,10 +77,11 @@ module lsu_tb;
#10ns clk = ~clk;
end
program testbench (mem_if slave);
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;
@ -86,5 +90,5 @@ module lsu_tb;
end
endprogram
testbench tb (slave);
testbench tb (slave, lsu);
endmodule