Conversation
martin-velay
left a comment
There was a problem hiding this comment.
I have added some comments, but I am still not done, I'll do another batch later. There are still some coding style issues
| @@ -0,0 +1,306 @@ | |||
| // This AXI4 VIP shall be always UVM_PASSIVE on top level | |||
There was a problem hiding this comment.
The copyright header is missing
| typedef enum bit[2:0] { | ||
| mst0 = 0, | ||
| slv0 = 1, | ||
| slv1 = 2, | ||
| slv2 = 3, | ||
| slv3 = 4 | ||
| } axi_if_t; |
There was a problem hiding this comment.
Would it be possible to change the field names into something more explicit like that maybe:
| typedef enum bit[2:0] { | |
| mst0 = 0, | |
| slv0 = 1, | |
| slv1 = 2, | |
| slv2 = 3, | |
| slv3 = 4 | |
| } axi_if_t; | |
| typedef enum bit[2:0] { | |
| mst0_cva6 = 0, | |
| slv0_sram = 1, | |
| slv1_mailbox = 2, | |
| slv2_tl_xbar = 3, | |
| slv3_dram = 4 | |
| } axi_if_t; |
There was a problem hiding this comment.
top_pkg field names are used.
| // AXI VIP configuration | ||
| axi_cfg = new[NUM_OF_AXI_IFS]; | ||
| env.cfg.m_axi_cfg = new[NUM_OF_AXI_IFS]; | ||
| foreach(axi_cfg[i]) begin |
There was a problem hiding this comment.
Nit: you need a space here and same below for the case. Can you please check else where in your code that you follow this rule.
https://github.com/lowRISC/style-guides/blob/master/VerilogCodingStyle.md#space-around-keywords
|
|
||
| foreach (actual_q[s]) foreach (actual_q[s][i]) if (actual_q[s][i].size() > 0) | ||
| `uvm_error("SCB_DRAIN", $sformatf("Slave trans on %s (ID %h) never reached Master", s, i)) | ||
| endfunction : check_phase No newline at end of file |
There was a problem hiding this comment.
You need to configure your editor to make sure you insert an empty line at the end of each file (it's also part of the coding rules somewhere)
| string slave_name; | ||
| bit [63:0] start_addr; | ||
| bit [63:0] end_addr; | ||
| } local_addr_range_t; |
There was a problem hiding this comment.
Can you move this typedef into the env_pkg
| int unsigned master_id_width = 4; | ||
|
|
||
| // Analysis Implementation Ports | ||
| `uvm_analysis_imp_decl(_mst0) |
There was a problem hiding this comment.
In the names if we can make it clearer which block is connected, as commented in the env_pkg, that would be better for debug purposes
There was a problem hiding this comment.
Updated using the top_pkg names
|
|
||
| // Queues to handle out-of-order monitor arrivals | ||
| // [SlaveName][MaskedID] | ||
| axi4_vip_item expect_q[string][bit[63:0]][$]; // Master arrived first |
There was a problem hiding this comment.
Is this 64 bits width linked with top_pkg::AxiDataWidth? It's better to point to a pkg value, this should be applied wherever required in this PR
There was a problem hiding this comment.
This is ID width to handle when the interconnect extends the ID width to be able to back-route the transactions to the managers. However, good spot, the scoreboard cuts the unnecessary bits before anything is pushed to this queue. Replaced by parameter.
| mem_map.push_back('{"slv0", 64'h1000_0000, 64'h1001_FFFF}); | ||
| mem_map.push_back('{"slv1", 64'h2001_0000, 64'h2001_FFFF}); | ||
| mem_map.push_back('{"slv2", 64'h4000_0000, 64'h4FFF_FFFF}); | ||
| mem_map.push_back('{"slv3", 64'h8000_0000, 64'hBF7F_FFFF}); |
There was a problem hiding this comment.
Here, the same applies, could you point at the pkg values please axi_addr_start_t
|
|
||
| function string top_chip_dv_axi_scoreboard::decode_addr(bit [63:0] addr); | ||
| foreach (mem_map[i]) begin | ||
| if (addr >= mem_map[i].start_addr && addr <= mem_map[i].end_addr) |
There was a problem hiding this comment.
You need to add the begin...end for each if whenever it doesn't fit on a single line as a rule. But as we talk about DV here, I'd prefer to add the begin...end and always jump a line this will facilitate breakpoint debug
|
|
||
| function void top_chip_dv_axi_scoreboard::check_phase(uvm_phase phase); | ||
| super.check_phase(phase); | ||
| foreach (expect_q[s]) foreach (expect_q[s][i]) if (expect_q[s][i].size() > 0) |
There was a problem hiding this comment.
This should be break down into multi lines and I think one foreach is useless:
| foreach (expect_q[s]) foreach (expect_q[s][i]) if (expect_q[s][i].size() > 0) | |
| foreach (expect_q[s][i]) begin | |
| if (expect_q[s][i].size() > 0) begin | |
| `uvm_error("SCB_DRAIN", $sformatf("Master req for %s (ID %h) never reached Slave", s, i)) | |
| end |
| // maximum supported bus widths | ||
| `define AXI4_MAX_ID_WIDTH 16 | ||
| `define AXI4_MAX_ADDR_WIDTH 64 | ||
| `define AXI4_MAX_DATA_WIDTH 512 |
There was a problem hiding this comment.
Is there a reason why DATA_WIDTH 1024 is not supported?
There was a problem hiding this comment.
Updated to 1024.
| if (current_burst == null) current_burst = axi4_vip_item::type_id::create("w_burst"); | ||
|
|
||
| current_burst.dir = AXI_WRITE; | ||
| current_burst.wdata.push_back(vif.monitor_cb.wdata & ((64'h1 << m_cfg.m_data_width) - 1)); |
There was a problem hiding this comment.
Shouldn't this be 512'h1 (or 1024'h1) for all rdata and wdata types?
There was a problem hiding this comment.
Updated with the given define.
|
|
||
| // Local Address Map Struct | ||
| typedef struct { | ||
| string slave_name; |
There was a problem hiding this comment.
Nit: the new nomenclature of AXI uses manager and subordinate.
There was a problem hiding this comment.
Yes, we talked about this. Is it better if the naming matches the AXI standard or the current RTL. I know, the new standard uses manager and subordinate, but the RTL uses master and slave.
There was a problem hiding this comment.
Good point. I'd say that we should follow the latest nomenclature with manager/subordinate. So it might be that the RTL needs to be changed? But from our concern in this VIP, as its purpose goes beyond this particular DUT eventually, I'd suggest to use the new wording. Do you think there will be some confusing piece of code where the 2 kinds will live together?
There was a problem hiding this comment.
Updated names.
| begin | ||
| bit [63:0] addr = (tr.dir == AXI_WRITE) ? tr.awaddr : tr.araddr; | ||
| bit [63:0] id = (tr.dir == AXI_WRITE) ? tr.awid : tr.arid; | ||
| // Note: resp logic simplified here for example; normally bit-sliced per beat |
There was a problem hiding this comment.
Can you please formulate this comment more precise?
There was a problem hiding this comment.
This is a legacy comment from a previous version. Thanks for spotting it. Removed.
Signed-off-by: Csaba Kiss <csaba.kiss@semify-eda.com>
Signed-off-by: Csaba Kiss <csaba.kiss@semify-eda.com>
…top UVM environment Signed-off-by: Csaba Kiss <csaba.kiss@semify-eda.com>
f698608 to
78b7a22
Compare
| bit m_has_checker = 1; | ||
|
|
||
| // actual bus widths (<= max defines) | ||
| int unsigned m_id_width = 16; |
There was a problem hiding this comment.
It does not really matter, because the configuration object is set in the test base. However, it does not hurt. Updating.
rswarbrick
left a comment
There was a problem hiding this comment.
Here are some initial notes. I've got half way through axi4_vip_monitor.svh from the first commit.
| targets: | ||
| default: | ||
| filesets: | ||
| - files_dv No newline at end of file |
There was a problem hiding this comment.
Obviously a minor nit, but I'd suggest sticking a \n at the end.
And the same for the other files missing newlines.
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| `ifndef AXI4_VIP_CFG_SVH |
There was a problem hiding this comment.
Why have we got include guards here? They make me raise my eyebrows: fusesoc is supposed to avoid us needing this...
There was a problem hiding this comment.
If you have a process to avoid double definition, I can remove the guards. However, they are pretty useful for larger projects.
| uvm_active_passive_enum m_subordinate_active_passive = UVM_PASSIVE; | ||
|
|
||
| // Future placeholders | ||
| bit m_has_coverage = 1; |
There was a problem hiding this comment.
I'm a bit surprised if a future placeholder that tracks if we have coverage/checker starts equal to 1. Shouldn't they be zero for now?
| int unsigned region_width = 8, | ||
| int unsigned qos_width = 8 | ||
| ); | ||
| m_inst_id = inst_id; |
There was a problem hiding this comment.
Minor nit, but I'd probably suggest lining this up with the next line.
| clocking manager_cb @(posedge aclk); | ||
|
|
||
| // write address | ||
| output awvalid, awid, awaddr, awlen, awsize, awburst; |
There was a problem hiding this comment.
How does this work in passive mode? Don't you want a wire and an output-enable flag?
There was a problem hiding this comment.
The monitor uses the monitor_cb. manager_cb and subordinta_cb will be used in the drivers in the future. Here you can see them for completeness.
| super.build_phase(phase); | ||
|
|
||
| if (!uvm_config_db#(axi4_vip_cfg)::get(this,"","m_cfg",m_cfg)) begin | ||
| `uvm_fatal("NOCFG", {"Configuration item must be set for: ", get_full_name(), "m_cfg"}) |
| function void axi4_vip_manager_agent::build_phase(uvm_phase phase); | ||
| super.build_phase(phase); | ||
|
|
||
| if (!uvm_config_db#(axi4_vip_cfg)::get(this,"","m_cfg",m_cfg)) begin |
There was a problem hiding this comment.
Nit: I think it's more conventional to have spaces after commas in argument lists.
| begin b_proc = process::self(); collect_b_channel(); end | ||
| begin ar_proc = process::self(); collect_ar_channel(); end | ||
| begin r_proc = process::self(); collect_r_channel(); end | ||
| join_none |
There was a problem hiding this comment.
Couldn't you structure this without the join_none? Something like this would work, I think:
fork
begin aw_proc = process::self(); collect_aw_channel(); end
...
begin r_proc = process::self(); collect_r_channel(); end
begin
wait(!vif.aresetn);
stop_processes();
end
join
cleanup_queues();There was a problem hiding this comment.
I think the 2 implementations are equivalent from functional point of view. Would you like me to change it?
| endtask : run_phase | ||
|
|
||
| function void axi4_vip_monitor::stop_processes(); | ||
| process p_list[$] = {aw_proc, w_proc, b_proc, ar_proc, r_proc}; |
There was a problem hiding this comment.
This is kind of ok, but I don't think we really care about naming the elements of the list. Can't you just make the class variable the list itself, and make the items in the run_phase method be more like proc_list.push_back(process::self()) ?
That will also simplify the code in the loop below (because we'll never push null into the list)
| endfunction : cleanup_queues | ||
|
|
||
| task axi4_vip_monitor::collect_aw_channel(); | ||
| bit [`AXI4_MAX_ID_WIDTH-1:0] id_one = 1'b1; |
There was a problem hiding this comment.
Couldn't we build the masks here instead of needing a bunch of "one" variables? I'm imagining things like this:
bit [`AXI4_MAX_ID_WIDTH-1:0] id_mask = {m_cfg.m_id_width{1'b1}};That said, I'm a little unsure about the masks in general. It seems strange to me for the monitor to be responsible for figuring out the bit width of the consumer or the bus itself.
There was a problem hiding this comment.
The implementation could be updated. The masking itself is useful when an interconnect adds extra ID bits to be able to route back the response to the right master. In this case, the VIP shall be configured properly, otherwise the scoreboard cannot recognize if the transactions are matching on the upstream and downstream side. This is just a general solution, currently not used.

Tested with top level test cases.
Will close issue #168