Skip to content

Commit

Permalink
[hw,dma,rtl] Add support for a memset operation
Browse files Browse the repository at this point in the history
Signed-off-by: Robert Schilling <[email protected]>
  • Loading branch information
Razer6 committed Aug 14, 2024
1 parent 9d58bef commit 9b1f90e
Show file tree
Hide file tree
Showing 8 changed files with 570 additions and 438 deletions.
20 changes: 19 additions & 1 deletion hw/ip/dma/data/dma.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,20 @@
}
]
}
{ name: "MEMSET_VALUE"
desc: "Memset value register used to define value that gets written during a memset operation."
swaccess: "rw"
hwaccess: "hro"
regwen: "CFG_REGWEN"
fields: [
{ bits: "31:0"
name: "memset_value"
resval: 0x0
desc: "Denotes the value that gets written during a memset operation."
}
]
tags: ["excl:CsrAllTests:CsrExclWrite"]
}
{ name: "CONTROL"
desc: "Control register for DMA data movement."
swaccess: "rw"
Expand Down Expand Up @@ -448,6 +462,10 @@
name: "SHA512"
desc: "Perform inline hashing using SHA512."
}
{ value: "4",
name: "MEMSET"
desc: "Perform a memset operation."
}
]
}
{ bits: "4"
Expand Down Expand Up @@ -721,7 +739,7 @@
]
}
}
{ skipto: "0x11C" }
{ skipto: "0x120" }
{ multireg: {
name: "INTR_SRC_WR_VAL"
desc: "Write value for interrupt clearing write."
Expand Down
195 changes: 107 additions & 88 deletions hw/ip/dma/doc/registers.md

Large diffs are not rendered by default.

44 changes: 27 additions & 17 deletions hw/ip/dma/dv/env/dma_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ class dma_scoreboard extends cip_base_scoreboard #(
endfunction

// On-the-fly checking of write data against the pre-randomized source data
function void check_write_data(string if_name, bit [63:0] a_addr, ref tl_seq_item item);
function void check_write_data(string if_name, bit [63:0] a_addr, ref tl_seq_item item,
ref dma_seq_item dma_config);
bit [tl_agent_pkg::DataWidth-1:0] wdata = item.a_data;
bit [31:0] offset = num_bytes_transferred;

Expand All @@ -179,10 +180,12 @@ class dma_scoreboard extends cip_base_scoreboard #(
// Check each of the bytes being written, Little Endian byte ordering
for (int i = 0; i < $bits(item.a_mask); i++) begin
if (item.a_mask[i]) begin
`uvm_info(`gfn, $sformatf("src_data %0x write data 0x%0x",
cfg.src_data[offset], wdata[7:0]), UVM_DEBUG)
`DV_CHECK_EQ(cfg.src_data[offset], wdata[7:0])
offset++;
if (dma_config.opcode != OpcMemset) begin
`uvm_info(`gfn, $sformatf("src_data %0x write data 0x%0x",
cfg.src_data[offset], wdata[7:0]), UVM_DEBUG)
`DV_CHECK_EQ(cfg.src_data[offset], wdata[7:0])
offset++;
end
end
wdata = wdata >> 8;
end
Expand Down Expand Up @@ -344,7 +347,7 @@ class dma_scoreboard extends cip_base_scoreboard #(
num_bytes_this_txn, intr_source), UVM_HIGH);

// On-the-fly checking of writing data
check_write_data(if_name, a_addr, item);
check_write_data(if_name, a_addr, item, dma_config);

// Check if opcode is as expected
if ((dma_config.per_transfer_width != DmaXfer4BperTxn) ||
Expand Down Expand Up @@ -765,18 +768,20 @@ class dma_scoreboard extends cip_base_scoreboard #(
bit [7:0] src_data = cfg.src_data[src_offset + i];
bit [7:0] dst_data;

if (dst_fifo) begin
dst_data = get_fifo_data(dma_config.dst_asid, dst_addr);
end else begin
dst_data = get_model_data(dma_config.dst_asid, dst_addr);
if (dma_config.opcode != OpcMemset) begin
if (dst_fifo) begin
dst_data = get_fifo_data(dma_config.dst_asid, dst_addr);
end else begin
dst_data = get_model_data(dma_config.dst_asid, dst_addr);
end
`uvm_info(`gfn,
$sformatf("checking src_addr = %0x data = %0x : dst_addr = %0x data = %0x",
src_addr, src_data, dst_addr, dst_data), UVM_DEBUG)
`DV_CHECK_EQ(src_data, dst_data,
$sformatf("src_addr = %0x data = %0x : dst_addr = %0x data = %0x",
src_addr, src_data, dst_addr, dst_data))
src_addr++;
end
`uvm_info(`gfn,
$sformatf("checking src_addr = %0x data = %0x : dst_addr = %0x data = %0x",
src_addr, src_data, dst_addr, dst_data), UVM_DEBUG)
`DV_CHECK_EQ(src_data, dst_data,
$sformatf("src_addr = %0x data = %0x : dst_addr = %0x data = %0x",
src_addr, src_data, dst_addr, dst_data))
src_addr++;
if (!dst_fifo) begin
dst_addr++;
end
Expand Down Expand Up @@ -895,6 +900,11 @@ class dma_scoreboard extends cip_base_scoreboard #(
`uvm_info(`gfn, $sformatf("Got transfer_width = %s",
dma_config.per_transfer_width.name()), UVM_HIGH)
end
"memset_value": begin
dma_config.memset_value = item.a_data;
`uvm_info(`gfn, $sformatf("Got memset_value = %0x B",
dma_config.memset_value), UVM_HIGH)
end
"clear_intr_bus": begin
dma_config.clear_intr_bus = `gmv(ral.clear_intr_bus.bus);
end
Expand Down
76 changes: 44 additions & 32 deletions hw/ip/dma/dv/env/dma_seq_item.sv
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class dma_seq_item extends uvm_sequence_item;
rand bit [31:0] mem_range_limit;
rand bit [31:0] total_data_size;
rand bit [31:0] chunk_data_size;
rand bit [31:0] memset_value;
rand mubi4_t range_regwen;
rand opcode_e opcode;
rand dma_transfer_width_e per_transfer_width;
Expand Down Expand Up @@ -100,6 +101,7 @@ class dma_seq_item extends uvm_sequence_item;
`uvm_field_enum(mubi4_t, range_regwen, UVM_DEFAULT)
`uvm_field_int(total_data_size, UVM_DEFAULT)
`uvm_field_int(chunk_data_size, UVM_DEFAULT)
`uvm_field_int(memset_value, UVM_DEFAULT)
`uvm_field_enum(dma_transfer_width_e, per_transfer_width, UVM_DEFAULT)
`uvm_field_int(auto_inc_buffer, UVM_DEFAULT)
`uvm_field_int(auto_inc_fifo, UVM_DEFAULT)
Expand Down Expand Up @@ -436,7 +438,8 @@ class dma_seq_item extends uvm_sequence_item;
$sformatf("\n\topcode : %0d", opcode),
$sformatf("\n\tper_transfer_width : %0d", per_transfer_width),
$sformatf("\n\tchunk_data_size : 0x%x", chunk_data_size),
$sformatf("\n\ttotal_data_size : 0x%x", total_data_size)
$sformatf("\n\ttotal_data_size : 0x%x", total_data_size),
$sformatf("\n\tmemset_value : 0x%x", memset_value)
};

// Verdict on whether this is a valid DMA configuration, eg. post-randomization
Expand Down Expand Up @@ -492,12 +495,15 @@ class dma_seq_item extends uvm_sequence_item;
// Use of the System bus is not invalid per se, but there are additional constraints that
// have had to be introduced to permit testing in block level DV (see `soc_system_hi_addr`
// above); if the upper bits do not match then reads or writes will be faulted, and 32-bit
// address wraparound is not permitted.
if (src_asid == SocSystemAddr) begin
if (src_addr[63:32] != soc_system_hi_addr || src_addr[31:0] >= ~memory_range) begin
`uvm_info(`gfn, " - Limitations of 32-bit TL-UL for testing System bus Reads not met",
UVM_MEDIUM)
valid_config = 0;
// address wraparound is not permitted.
// No surce checks needed when doing a memset operation
if (opcode != OpcMemset) begin
if (src_asid == SocSystemAddr) begin
if (src_addr[63:32] != soc_system_hi_addr || src_addr[31:0] >= ~memory_range) begin
`uvm_info(`gfn, " - Limitations of 32-bit TL-UL for testing System bus Reads not met",
UVM_MEDIUM)
valid_config = 0;
end
end
end
if (dst_asid == SocSystemAddr) begin
Expand All @@ -517,9 +523,12 @@ class dma_seq_item extends uvm_sequence_item;
`uvm_info(`gfn, " - Destination ASID invalid", UVM_MEDIUM)
valid_config = 0;
end
if (!(src_asid inside {OtInternalAddr, SocControlAddr, SocSystemAddr})) begin
`uvm_info(`gfn, " - Source ASID invalid", UVM_MEDIUM)
valid_config = 0;
// Source ASID check not needed in memset operation
if (opcode != OpcMemset) begin
if (!(src_asid inside {OtInternalAddr, SocControlAddr, SocSystemAddr})) begin
`uvm_info(`gfn, " - Source ASID invalid", UVM_MEDIUM)
valid_config = 0;
end
end

// Check if operation is valid
Expand All @@ -528,7 +537,7 @@ class dma_seq_item extends uvm_sequence_item;
`uvm_info(`gfn, $sformatf(" - SHA hashing operates only on 4B/txn"), UVM_MEDIUM)
valid_config = 0;
end
end else if (opcode != OpcCopy) begin
end else if (!(opcode inside {OpcCopy, OpcMemset})) begin
`uvm_info(`gfn, $sformatf(" - Unsupported DMA operation: %s", opcode.name()), UVM_MEDIUM)
valid_config = 0;
end
Expand All @@ -549,27 +558,30 @@ class dma_seq_item extends uvm_sequence_item;
// For all valid configurations, either source or destination address space Id must point
// to OT internal address space, but the memory range restriction does not apply if _both_
// are within the OT internal address space.
if (src_asid == OtInternalAddr && dst_asid != OtInternalAddr) begin
if (mem_range_valid && !is_buffer_in_dma_memory_region(src_addr[31:0], memory_range)) begin
// If source address space ID points to OT internal address space,
// it must be within DMA enabled address range.
`uvm_info(`gfn,
$sformatf(
" - Invalid src addr range found lo: %08x hi: %08x with base: %08x limit: %0x",
src_addr[31:0], src_addr[63:32], mem_range_base, mem_range_limit),
UVM_MEDIUM)
valid_config = 0;
end
end else if (dst_asid == OtInternalAddr && src_asid != OtInternalAddr) begin
// If destination address space ID points to OT internal address space
// it must be within DMA enabled address range.
if (mem_range_valid && !is_buffer_in_dma_memory_region(dst_addr[31:0], memory_range)) begin
`uvm_info(`gfn,
if (opcode != OpcMemset) begin
if (src_asid == OtInternalAddr && dst_asid != OtInternalAddr) begin
if (mem_range_valid && !is_buffer_in_dma_memory_region(src_addr[31:0], memory_range)) begin
// If source address space ID points to OT internal address space,
// it must be within DMA enabled address range.
`uvm_info(`gfn,
$sformatf(
" - Invalid dst addr range found lo: %08x hi: %08x with base: %08x limit: %0x",
dst_addr[31:0], dst_addr[63:32], mem_range_base, mem_range_limit),
" - Invalid src addr range found lo: %08x hi: %08x with base: %08x limit: %0x",
src_addr[31:0], src_addr[63:32], mem_range_base, mem_range_limit),
UVM_MEDIUM)
valid_config = 0;
valid_config = 0;
end
end else if (dst_asid == OtInternalAddr && src_asid != OtInternalAddr) begin
// If destination address space ID points to OT internal address space
// it must be within DMA enabled address range.
if (mem_range_valid && !is_buffer_in_dma_memory_region(dst_addr[31:0], memory_range)) begin
`uvm_info(`gfn,
$sformatf(
" - Invalid dst addr range found lo: %08x hi: %08x with base: %08x \
limit: %0x",
dst_addr[31:0], dst_addr[63:32], mem_range_base, mem_range_limit),
UVM_MEDIUM)
valid_config = 0;
end
end
end

Expand All @@ -579,7 +591,7 @@ class dma_seq_item extends uvm_sequence_item;
`uvm_info(`gfn, " - Destination address out of range for destination ASID", UVM_MEDIUM)
valid_config = 0;
end
if (src_asid != SocSystemAddr && |src_addr[63:32]) begin
if (opcode != OpcMemset && src_asid != SocSystemAddr && |src_addr[63:32]) begin
`uvm_info(`gfn, " - Source addess out of range for source ASID", UVM_MEDIUM)
valid_config = 0;
end
Expand All @@ -596,7 +608,7 @@ class dma_seq_item extends uvm_sequence_item;
end
endcase

if (|(src_addr & align_mask)) begin
if (opcode != OpcMemset && |(src_addr & align_mask)) begin
`uvm_info(`gfn, " - Source address does not meet alignment requirements", UVM_MEDIUM)
valid_config = 0;
end
Expand Down
Loading

0 comments on commit 9b1f90e

Please sign in to comment.