-
Notifications
You must be signed in to change notification settings - Fork 19
AXI4 VIP development and integration #688
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
e686aa6
579723f
b59c688
76a5434
0ab815d
eeea7ec
8676709
c1089f4
e078470
270499c
a474fd2
ebca3b5
c161b61
5df0054
fa138f2
525ed3e
216931e
a20857e
f123077
5a23f42
e9265c4
7b39df5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| CAPI=2: | ||
| # Copyright lowRISC contributors. | ||
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| name: "lowrisc:dv:axi_agent:0.1" | ||
| description: "AXI agent" | ||
| filesets: | ||
| files_dv: | ||
| depend: | ||
| - lowrisc:dv:dv_utils | ||
| - lowrisc:dv:common_ifs | ||
| files: | ||
| - axi_read_data_if.sv | ||
| - axi_read_request_if.sv | ||
| - axi_write_data_if.sv | ||
| - axi_write_request_if.sv | ||
| - axi_write_response_if.sv | ||
|
|
||
| - axi_agent_pkg.sv | ||
| - axi_agent_cfg.svh: {is_include_file: true} | ||
|
|
||
| - axi_mon_types.svh: {is_include_file: true} | ||
| - axi_mon_item.svh: {is_include_file: true} | ||
| - axi_mon_write_item.svh: {is_include_file: true} | ||
| - axi_mon_read_item.svh: {is_include_file: true} | ||
| - axi_monitor.svh: {is_include_file: true} | ||
|
|
||
| - axi_reset_item.svh: {is_include_file: true} | ||
| - axi_status_item.svh: {is_include_file: true} | ||
| - axi_txn_request_item.svh: {is_include_file: true} | ||
| - axi_response_accept_item.svh: {is_include_file: true} | ||
| - axi_read_data_item.svh: {is_include_file: true} | ||
| - axi_write_data_item.svh: {is_include_file: true} | ||
| - axi_write_response_item.svh: {is_include_file: true} | ||
|
|
||
| - axi_fixed_write_req_item.svh: {is_include_file: true} | ||
| - axi_fixed_write_rsp_item.svh: {is_include_file: true} | ||
| - axi_fixed_read_req_item.svh: {is_include_file: true} | ||
| - axi_fixed_read_rsp_item.svh: {is_include_file: true} | ||
|
|
||
| - axi_reset_monitor.svh: {is_include_file: true} | ||
|
|
||
| - axi_mgr_write_request_driver.svh: {is_include_file: true} | ||
| - axi_mgr_write_data_driver.svh: {is_include_file: true} | ||
| - axi_mgr_write_response_driver.svh: {is_include_file: true} | ||
| - axi_mgr_read_request_driver.svh: {is_include_file: true} | ||
| - axi_mgr_read_data_driver.svh: {is_include_file: true} | ||
|
|
||
| - axi_response_router.svh: {is_include_file: true} | ||
|
|
||
| - axi_reg_op_item.svh: {is_include_file: true} | ||
| - axi_reg_adapter.svh: {is_include_file: true} | ||
|
|
||
| - axi_mgr_agent.svh: {is_include_file: true} | ||
|
|
||
| - seq_lib/axi_mgr_txn_request_seq.svh: {is_include_file: true} | ||
| - seq_lib/axi_mgr_write_data_seq.svh: {is_include_file: true} | ||
| - seq_lib/axi_mgr_write_single_data_seq.svh: {is_include_file: true} | ||
| - seq_lib/axi_mgr_write_listed_data_seq.svh: {is_include_file: true} | ||
| - seq_lib/axi_mgr_write_response_seq.svh: {is_include_file: true} | ||
| - seq_lib/axi_mgr_read_data_seq.svh: {is_include_file: true} | ||
|
|
||
| - seq_lib/axi_mgr_write_fixed_vseq.svh: {is_include_file: true} | ||
| - seq_lib/axi_mgr_write_burst_vseq.svh: {is_include_file: true} | ||
| - seq_lib/axi_mgr_read_fixed_vseq.svh: {is_include_file: true} | ||
| - seq_lib/axi_mgr_read_burst_vseq.svh: {is_include_file: true} | ||
|
|
||
| - seq_lib/axi_mgr_register_layer_vseq.svh: {is_include_file: true} | ||
|
|
||
| file_type: systemVerilogSource | ||
|
|
||
| targets: | ||
| default: | ||
| filesets: | ||
| - files_dv | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| // Copyright lowRISC contributors | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| // The configuration for an agent driving the interfaces for AXI (AW, W, B, AR, R). | ||
|
|
||
| class axi_agent_cfg extends uvm_object; | ||
| `uvm_object_utils(axi_agent_cfg) | ||
|
|
||
| // Interfaces | ||
| virtual clk_rst_if clk_rst_vif; // ACLK/ARESETn | ||
|
|
||
|
tchilikov-semify marked this conversation as resolved.
|
||
| virtual axi_write_request_if write_request_vif; | ||
| virtual axi_write_data_if write_data_vif; | ||
| virtual axi_write_response_if write_response_vif; | ||
| virtual axi_read_request_if read_request_vif; | ||
| virtual axi_read_data_if read_data_vif; | ||
|
|
||
| // ID and knobs | ||
| string inst_id = "axi_mgr"; // tag for logging | ||
| uvm_active_passive_enum is_active = UVM_ACTIVE; // gates the driver; the monitor is always built | ||
| bit enable_coverage = 1'b0; | ||
|
|
||
| extern function new(string name = "axi_agent_cfg"); | ||
|
|
||
| // Set the config fields in one call. Interfaces are set by the VIP instantiation. | ||
| extern function void set_config(string inst_id = "axi_mgr", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm really not a fan of big lines of arguments with default values. As I wrote above, I think you only need to set
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that the other fields were not needed - However I think that the inst_id carries value and should be kept. This field is rather useful for logging and debugging when there are multiple VIP instances. Even in our current integration, we have multiple monitors. I like the idea of being able to set a descriptive name for each instance that can show up on the logs. As for the default values - I can remove these, although since its only 3 values, I dont think they hinder much. Let me know what you prefer for both! |
||
| uvm_active_passive_enum is_active = UVM_ACTIVE, | ||
| bit enable_coverage = 1'b0); | ||
| endclass | ||
|
|
||
| function axi_agent_cfg::new(string name = "axi_agent_cfg"); | ||
| super.new(name); | ||
| endfunction | ||
|
|
||
| function void axi_agent_cfg::set_config(string inst_id = "axi_mgr", | ||
| uvm_active_passive_enum is_active = UVM_ACTIVE, | ||
| bit enable_coverage = 1'b0); | ||
| this.inst_id = inst_id; | ||
| this.is_active = is_active; | ||
| this.enable_coverage = enable_coverage; | ||
| endfunction | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| // Copyright lowRISC contributors | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| package axi_agent_pkg; | ||
| import uvm_pkg::*; | ||
| `include "uvm_macros.svh" | ||
|
|
||
| // The possible encodings of the AxBURST signal | ||
| typedef enum bit [1:0] { | ||
| BurstFixed = 0, | ||
| BurstIncr = 1, | ||
| BurstWrap = 2 | ||
| } burst_e; | ||
|
|
||
| `include "axi_agent_cfg.svh" | ||
|
|
||
| `include "axi_txn_request_item.svh" | ||
| `include "axi_read_data_item.svh" | ||
|
|
||
| `include "axi_write_data_item.svh" | ||
| `include "axi_write_response_item.svh" | ||
|
|
||
| `include "axi_response_accept_item.svh" | ||
|
|
||
| `include "axi_status_item.svh" | ||
|
|
||
| `include "axi_mgr_write_request_driver.svh" | ||
| `include "axi_mgr_write_data_driver.svh" | ||
| `include "axi_mgr_write_response_driver.svh" | ||
|
|
||
| `include "axi_mgr_read_request_driver.svh" | ||
| `include "axi_mgr_read_data_driver.svh" | ||
|
|
||
| `include "axi_reset_item.svh" | ||
|
|
||
| // Reset monitor for the shared AXI clock/reset (one instance covers all channels). | ||
| `include "axi_reset_monitor.svh" | ||
|
|
||
| `include "axi_reg_op_item.svh" | ||
| `include "axi_reg_adapter.svh" | ||
|
|
||
| typedef uvm_sequencer#(axi_txn_request_item, axi_status_item) write_request_sequencer_t; | ||
| typedef uvm_sequencer#(axi_write_data_item, axi_status_item) write_data_sequencer_t; | ||
| typedef uvm_sequencer#(axi_response_accept_item, uvm_sequence_item) write_response_sequencer_t; | ||
| typedef uvm_sequencer#(axi_txn_request_item, axi_status_item) read_request_sequencer_t; | ||
| typedef uvm_sequencer#(axi_response_accept_item, uvm_sequence_item) read_data_sequencer_t; | ||
| typedef uvm_sequencer#(axi_reg_op_item, uvm_sequence_item) reg_op_sequencer_t; | ||
|
|
||
| `include "axi_response_router.svh" | ||
|
|
||
| `include "seq_lib/axi_mgr_txn_request_seq.svh" | ||
| `include "seq_lib/axi_mgr_write_data_seq.svh" | ||
| `include "seq_lib/axi_mgr_write_single_data_seq.svh" | ||
| `include "seq_lib/axi_mgr_write_listed_data_seq.svh" | ||
| `include "seq_lib/axi_mgr_write_response_seq.svh" | ||
| `include "seq_lib/axi_mgr_read_data_seq.svh" | ||
|
|
||
| `include "axi_fixed_write_req_item.svh" | ||
| `include "axi_fixed_write_rsp_item.svh" | ||
| `include "seq_lib/axi_mgr_write_fixed_vseq.svh" | ||
| `include "seq_lib/axi_mgr_write_burst_vseq.svh" | ||
|
|
||
| `include "axi_fixed_read_req_item.svh" | ||
| `include "axi_fixed_read_rsp_item.svh" | ||
| `include "seq_lib/axi_mgr_read_fixed_vseq.svh" | ||
| `include "seq_lib/axi_mgr_read_burst_vseq.svh" | ||
|
|
||
| `include "seq_lib/axi_mgr_register_layer_vseq.svh" | ||
|
|
||
| `include "axi_mon_types.svh" | ||
| `include "axi_mon_item.svh" | ||
| `include "axi_mon_write_item.svh" | ||
| `include "axi_mon_read_item.svh" | ||
| `include "axi_monitor.svh" | ||
|
|
||
| `include "axi_mgr_agent.svh" | ||
| endpackage |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| // Copyright lowRISC contributors | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| // A sequence item that represents the request that should be made to send a single AXI read with | ||
| // AWBURST set to FIXED and AWLEN = 0 (so just a single data transfer). | ||
|
|
||
| class axi_fixed_read_req_item extends uvm_sequence_item; | ||
| `uvm_object_utils(axi_fixed_read_req_item) | ||
| // Transaction identifier for the read channel | ||
| // | ||
| // This is sent as AWID, whose width is configurable (and will be checked against the | ||
| // corresponding width in the interface by the driver). | ||
| rand bit [31:0] m_id; | ||
|
|
||
| // The address. | ||
| // | ||
| // This is AWADDR, whose width is configurable (and will be checked against the | ||
| // corresponding width in the interface by the driver). | ||
| rand bit [63:0] m_addr; | ||
|
|
||
| // The region identifier, sent as AWREGION in the request transfer. | ||
| rand bit [3:0] m_region; | ||
|
|
||
| // Number of bytes in the data transfer. Sent as AWSIZE and encoded as log2(byte_size). | ||
| rand bit [2:0] m_size; | ||
|
|
||
| // Request exclusive access? Sent as AWLOCK. | ||
| rand bit m_lock; | ||
|
|
||
| // Memory attributes (applying to caches in the system). Sent as AWCACHE. | ||
| rand bit [3:0] m_cache; | ||
|
|
||
| // Memory access attributes. Sent as AWPROT. | ||
| rand bit [2:0] m_prot; | ||
|
|
||
| // Traffic stream QoS identifier. Sent as AWQOS. | ||
| rand bit [3:0] m_qos; | ||
|
|
||
| // Extra user bits. | ||
| // | ||
| // This is sent as AWUSER, whose width is configurable (and will be checked against the | ||
| // corresponding width in the interface by the driver). | ||
| rand bit [127:0] m_user; | ||
|
|
||
| extern function new(string name = ""); | ||
| extern function void do_print(uvm_printer printer); | ||
| extern function void do_copy(uvm_object rhs); | ||
| extern function bit do_compare(uvm_object rhs, uvm_comparer comparer); | ||
| endclass | ||
|
|
||
| function axi_fixed_read_req_item::new(string name = ""); | ||
| super.new(name); | ||
| endfunction | ||
|
|
||
| function void axi_fixed_read_req_item::do_print(uvm_printer printer); | ||
| super.do_print(printer); | ||
| printer.print_field_int("m_id", m_id, 32, UVM_HEX); | ||
| printer.print_field("m_addr", m_addr, 64, UVM_HEX); | ||
| printer.print_field_int("m_region", m_region, 4, UVM_HEX); | ||
| printer.print_field_int("m_size", m_size, 3, UVM_DEC); | ||
| printer.print_field_int("m_lock", m_lock, 1, UVM_BIN); | ||
| printer.print_field_int("m_cache", m_cache, 4, UVM_BIN); | ||
| printer.print_field_int("m_prot", m_prot, 3, UVM_BIN); | ||
| printer.print_field_int("m_qos", m_qos, 4, UVM_HEX); | ||
| printer.print_field("m_user", m_user, 128, UVM_HEX); | ||
| endfunction | ||
|
|
||
| function void axi_fixed_read_req_item::do_copy(uvm_object rhs); | ||
| axi_fixed_read_req_item rhs_; | ||
|
|
||
| if (rhs == null) `uvm_fatal("do_copy", "Cannot copy from RHS: it is null.") | ||
| if (!$cast(rhs_, rhs)) `uvm_fatal("do_copy", "Cannot cast RHS: wrong type?") | ||
|
|
||
| super.do_copy(rhs); | ||
| this.m_id = rhs_.m_id; | ||
| this.m_addr = rhs_.m_addr; | ||
| this.m_region = rhs_.m_region; | ||
| this.m_size = rhs_.m_size; | ||
| this.m_lock = rhs_.m_lock; | ||
| this.m_cache = rhs_.m_cache; | ||
| this.m_prot = rhs_.m_prot; | ||
| this.m_qos = rhs_.m_qos; | ||
| this.m_user = rhs_.m_user; | ||
| endfunction | ||
|
|
||
| function bit axi_fixed_read_req_item::do_compare(uvm_object rhs, uvm_comparer comparer); | ||
| axi_fixed_read_req_item rhs_; | ||
|
|
||
| // These items are only equivalent if rhs is actually an axi_fixed_read_req_item. | ||
| if (rhs == null || !$cast(rhs_, rhs)) begin | ||
| comparer.print_msg("RHS is null or is not an axi_fixed_read_req_item."); | ||
| return 0; | ||
| end | ||
|
|
||
| return (super.do_compare(rhs, comparer) & | ||
| comparer.compare_field_int("m_id", m_id, rhs_.m_id, 32, UVM_HEX) & | ||
| comparer.compare_field("m_addr", m_addr, rhs_.m_addr, 64, UVM_HEX) & | ||
| comparer.compare_field_int("m_region", m_region, rhs_.m_region, 4, UVM_HEX) & | ||
| comparer.compare_field_int("m_size", m_size, rhs_.m_size, 3, UVM_DEC) & | ||
| comparer.compare_field_int("m_lock", m_lock, rhs_.m_lock, 1, UVM_BIN) & | ||
| comparer.compare_field_int("m_cache", m_cache, rhs_.m_cache, 4, UVM_BIN) & | ||
| comparer.compare_field_int("m_prot", m_prot, rhs_.m_prot, 3, UVM_BIN) & | ||
| comparer.compare_field_int("m_qos", m_qos, rhs_.m_qos, 4, UVM_HEX) & | ||
| comparer.compare_field("m_user", m_user, rhs_.m_user, 128, UVM_HEX)); | ||
| endfunction |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| // Copyright lowRISC contributors | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| // A sequence item that represents a response to an AXI read with a single beat | ||
| // | ||
| // The fields are null when the instance is created, and should be filled with results of the two | ||
| // sequences (which may be null if the sequences were interrupted by a reset). | ||
|
|
||
| class axi_fixed_read_rsp_item extends uvm_sequence_item; | ||
| `uvm_object_utils(axi_fixed_read_rsp_item) | ||
| // The status of the read request transfer (which either completed or was interrupted by reset) | ||
| axi_status_item m_ar_status; | ||
|
|
||
| // The single read data item seen (on the R channel) | ||
| axi_read_data_item m_read_data; | ||
|
|
||
| extern function new(string name = ""); | ||
| extern function void do_print(uvm_printer printer); | ||
| extern function void do_copy(uvm_object rhs); | ||
| extern function bit do_compare(uvm_object rhs, uvm_comparer comparer); | ||
| endclass | ||
|
|
||
| function axi_fixed_read_rsp_item::new(string name = ""); | ||
| super.new(name); | ||
| endfunction | ||
|
|
||
| function void axi_fixed_read_rsp_item::do_print(uvm_printer printer); | ||
| super.do_print(printer); | ||
| printer.print_object("m_ar_status", m_ar_status); | ||
| printer.print_object("m_read_data", m_read_data); | ||
| endfunction | ||
|
|
||
| function void axi_fixed_read_rsp_item::do_copy(uvm_object rhs); | ||
| axi_fixed_read_rsp_item rhs_; | ||
|
|
||
| if (rhs == null) `uvm_fatal("do_copy", "Cannot copy from RHS: it is null.") | ||
| if (!$cast(rhs_, rhs)) `uvm_fatal("do_copy", "Cannot cast RHS: wrong type?") | ||
|
|
||
| super.do_copy(rhs); | ||
| if (rhs_.m_ar_status == null) m_ar_status = null; | ||
| else if (!$cast(m_ar_status, rhs_.m_ar_status.clone())) begin | ||
| `uvm_fatal("do_copy", "Failed to clone m_ar_status.") | ||
| end | ||
|
|
||
| if (rhs_.m_read_data == null) m_read_data = null; | ||
| else if (!$cast(m_read_data, rhs_.m_read_data.clone())) begin | ||
| `uvm_fatal("do_copy", "Failed to clone m_read_data.") | ||
| end | ||
| endfunction | ||
|
|
||
| function bit axi_fixed_read_rsp_item::do_compare(uvm_object rhs, uvm_comparer comparer); | ||
| bit all_match = 1; | ||
| axi_fixed_read_rsp_item rhs_; | ||
|
|
||
| // These items are only equivalent if rhs is actually an axi_fixed_read_rsp_item. | ||
| if (rhs == null || !$cast(rhs_, rhs)) begin | ||
| comparer.print_msg("RHS is null or is not an axi_fixed_read_rsp_item."); | ||
| return 0; | ||
| end | ||
|
|
||
| return (super.do_compare(rhs, comparer) & | ||
| comparer.compare_object("m_ar_status", m_ar_status, rhs_.m_ar_status) & | ||
| comparer.compare_object("m_read_data", m_read_data, rhs_.m_read_data)); | ||
| endfunction |
Uh oh!
There was an error while loading. Please reload this page.