mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 12:57:13 -04:00
Properly vendor in mem_model from OpenTitan
This removes the manually copied version at dv/uvm/core_ibex/common and vendors things properly now that the vendor tool supports such things (this picks up the same OpenTitan version as the previous commit: lowRISC/opentitan@067272a2).
This commit is contained in:
parent
e37c81a1c1
commit
46ff63ad88
8 changed files with 117 additions and 62 deletions
|
@ -46,8 +46,8 @@ execution.
|
|||
Memory Model
|
||||
""""""""""""
|
||||
|
||||
The code can be found in the
|
||||
`dv/uvm/core_ibex/common/mem_model <https://github.com/lowRISC/ibex/tree/master/dv/uvm/core_ibex/common/mem_model>`_
|
||||
The code is vendored from OpenTitan and can be found in the
|
||||
`vendor/lowrisc_ip/mem_model <https://github.com/lowRISC/ibex/tree/master/vendor/lowrisc_ip/mem_model>`_
|
||||
directory.
|
||||
The testbench instantiates a single instance of this memory model that it loads the compiled
|
||||
assembly test program into at the beginning of each test.
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
class mem_model#(parameter int ADDR_WIDTH = 32,
|
||||
parameter int DATA_WIDTH = 32) extends uvm_object;
|
||||
|
||||
typedef bit [ADDR_WIDTH-1:0] mem_addr_t;
|
||||
typedef bit [DATA_WIDTH-1:0] mem_data_t;
|
||||
|
||||
bit [7:0] system_memory[mem_addr_t];
|
||||
|
||||
`uvm_object_param_utils(mem_model#(ADDR_WIDTH, DATA_WIDTH))
|
||||
|
||||
function new(string name="");
|
||||
super.new(name);
|
||||
endfunction
|
||||
|
||||
function bit [7:0] read_byte(mem_addr_t addr);
|
||||
bit [7:0] data;
|
||||
if(system_memory.exists(addr)) begin
|
||||
data = system_memory[addr];
|
||||
`uvm_info(get_full_name(),
|
||||
$sformatf("Read Mem : Addr[0x%0h], Data[0x%0h]", addr, data), UVM_HIGH)
|
||||
end
|
||||
else begin
|
||||
`DV_CHECK_STD_RANDOMIZE_FATAL(data)
|
||||
`uvm_error(get_full_name(), $sformatf("read to uninitialzed addr 0x%0h", addr))
|
||||
end
|
||||
return data;
|
||||
endfunction
|
||||
|
||||
function void write_byte(mem_addr_t addr, bit[7:0] data);
|
||||
`uvm_info(get_full_name(),
|
||||
$sformatf("Write Mem : Addr[0x%0h], Data[0x%0h]", addr, data), UVM_HIGH)
|
||||
system_memory[addr] = data;
|
||||
endfunction
|
||||
|
||||
function void write(input mem_addr_t addr, mem_data_t data);
|
||||
bit [7:0] byte_data;
|
||||
for(int i=0; i<DATA_WIDTH/8; i++) begin
|
||||
byte_data = data[7:0];
|
||||
write_byte(addr+i, byte_data);
|
||||
data = data >> 8;
|
||||
end
|
||||
endfunction
|
||||
|
||||
function mem_data_t read(mem_addr_t addr);
|
||||
mem_data_t data;
|
||||
for(int i=DATA_WIDTH/8-1; i>=0; i--) begin
|
||||
data = data << 8;
|
||||
data[7:0] = read_byte(addr+i);
|
||||
end
|
||||
return data;
|
||||
endfunction
|
||||
|
||||
endclass
|
|
@ -61,13 +61,13 @@ ${PRJ_DIR}/ibex/vendor/google_riscv-dv/src/riscv_signature_pkg.sv
|
|||
+incdir+${PRJ_DIR}/ibex/dv/uvm/core_ibex/tests
|
||||
+incdir+${PRJ_DIR}/ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent
|
||||
+incdir+${PRJ_DIR}/ibex/dv/uvm/core_ibex/common/irq_agent
|
||||
+incdir+${PRJ_DIR}/ibex/dv/uvm/core_ibex/common/mem_model
|
||||
+incdir+${PRJ_DIR}/ibex/vendor/lowrisc_ip/mem_model
|
||||
+incdir+${PRJ_DIR}/ibex/vendor/lowrisc_ip/dv_utils
|
||||
${PRJ_DIR}/ibex/dv/uvm/top_pkg/top_pkg.sv
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/common_ifs/clk_rst_if.sv
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/common_ifs/pins_if.sv
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/dv_utils/dv_utils_pkg.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/core_ibex/common/mem_model/mem_model_pkg.sv
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/mem_model/mem_model_pkg.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_agent_pkg.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/core_ibex/common/irq_agent/irq_if.sv
|
||||
|
|
1
vendor/lowrisc_ip.vendor.hjson
vendored
1
vendor/lowrisc_ip.vendor.hjson
vendored
|
@ -15,6 +15,7 @@
|
|||
{from: "hw/dv/sv/csr_utils", to: "csr_utils"},
|
||||
{from: "hw/dv/sv/dv_lib", to: "dv_lib"},
|
||||
{from: "hw/dv/sv/dv_base_reg", to: "dv_base_reg"},
|
||||
{from: "hw/dv/sv/mem_model", to: "mem_model"},
|
||||
{from: "hw/dv/verilator", to: "dv_verilator"},
|
||||
|
||||
// We apply a patch to the top_pkg core file name when vendoring in
|
||||
|
|
26
vendor/lowrisc_ip/mem_model/README.md
vendored
Normal file
26
vendor/lowrisc_ip/mem_model/README.md
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
## Memory Model
|
||||
The memory model UVC models a memory device which any host interface can read
|
||||
from or write to. It is implemented as a `uvm_object`, and instantiates an
|
||||
associative array of bytes `system_memory`. This class is paramterized by both
|
||||
the address width and the data width, and creates two `typedefs` to represent
|
||||
both, `mem_addr_t` and `mem_data_t`.
|
||||
The `mem_model` class has four main functions, which are detailed below.
|
||||
|
||||
### `read_byte(mem_addr_t addr)`
|
||||
This function looks up the byte of data corresponding to the memory address
|
||||
passed in, and returns it. If the address does not exist in `system_memory`, it
|
||||
will randomize the returned data and throw a `UVM_ERROR`.
|
||||
|
||||
### `write_byte(mem_addr_t addr, bit [7:0] data)`
|
||||
This function simply assigns the given data to the specified memory address
|
||||
location in `system_memory`.
|
||||
|
||||
### `write(input mem_addr_t addr, mem_data_t data)`
|
||||
This function writes a full memory word of width `mem_data_t` to the specified
|
||||
address, breaking it down into a series of back-to-back calls to `write_byte()`
|
||||
to correctly byte-address the memory.
|
||||
|
||||
### `read(mem_addr_t addr)`
|
||||
This function reads a full memory word of width `mem_data_t` from the specified
|
||||
address, breaking it down into a series of back-to-back calls to `read_byte()`
|
||||
to correctly byte-address the memory.
|
|
@ -8,7 +8,7 @@ description: "DV Memory Model"
|
|||
filesets:
|
||||
files_dv:
|
||||
depend:
|
||||
- lowrisc:dv:dv_utils
|
||||
- lowrisc:constants:top_pkg
|
||||
files:
|
||||
- mem_model_pkg.sv
|
||||
- mem_model.sv: {is_include_file: true}
|
85
vendor/lowrisc_ip/mem_model/mem_model.sv
vendored
Normal file
85
vendor/lowrisc_ip/mem_model/mem_model.sv
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
class mem_model #(int AddrWidth = top_pkg::TL_AW,
|
||||
int DataWidth = top_pkg::TL_DW,
|
||||
int MaskWidth = top_pkg::TL_DBW) extends uvm_object;
|
||||
|
||||
typedef bit [AddrWidth-1:0] mem_addr_t;
|
||||
typedef bit [DataWidth-1:0] mem_data_t;
|
||||
typedef bit [MaskWidth-1:0] mem_mask_t;
|
||||
|
||||
bit [7:0] system_memory[mem_addr_t];
|
||||
|
||||
`uvm_object_param_utils(mem_model#(AddrWidth, DataWidth))
|
||||
|
||||
`uvm_object_new
|
||||
|
||||
function int get_written_bytes();
|
||||
return system_memory.size();
|
||||
endfunction
|
||||
|
||||
function bit [7:0] read_byte(mem_addr_t addr);
|
||||
bit [7:0] data;
|
||||
if (system_memory.exists(addr)) begin
|
||||
data = system_memory[addr];
|
||||
`uvm_info(`gfn, $sformatf("Read Mem : Addr[0x%0h], Data[0x%0h]", addr, data), UVM_HIGH)
|
||||
end else begin
|
||||
`DV_CHECK_STD_RANDOMIZE_FATAL(data)
|
||||
`uvm_error(`gfn, $sformatf("read to uninitialzed addr 0x%0h", addr))
|
||||
end
|
||||
return data;
|
||||
endfunction
|
||||
|
||||
function void write_byte(mem_addr_t addr, bit [7:0] data);
|
||||
`uvm_info(`gfn, $sformatf("Write Mem : Addr[0x%0h], Data[0x%0h]", addr, data), UVM_HIGH)
|
||||
system_memory[addr] = data;
|
||||
endfunction
|
||||
|
||||
function void compare_byte(mem_addr_t addr, bit [7:0] act_data);
|
||||
`uvm_info(`gfn, $sformatf("Compare Mem : Addr[0x%0h], Act Data[0x%0h], Exp Data[0x%0h]",
|
||||
addr, act_data, system_memory[addr]), UVM_HIGH)
|
||||
system_memory[addr] = act_data;
|
||||
`DV_CHECK_EQ(act_data, system_memory[addr], $sformatf("addr 0x%0h read out mismatch", addr))
|
||||
endfunction
|
||||
|
||||
function void write(input mem_addr_t addr, mem_data_t data, mem_mask_t mask = '1);
|
||||
bit [7:0] byte_data;
|
||||
for (int i = 0; i < DataWidth / 8; i++) begin
|
||||
if (mask[0]) begin
|
||||
byte_data = data[7:0];
|
||||
write_byte(addr + i, byte_data);
|
||||
end
|
||||
data = data >> 8;
|
||||
mask = mask >> 1;
|
||||
end
|
||||
endfunction
|
||||
|
||||
function mem_data_t read(mem_addr_t addr, mem_mask_t mask = '1);
|
||||
mem_data_t data;
|
||||
for (int i = DataWidth / 8 - 1; i >= 0; i--) begin
|
||||
data = data << 8;
|
||||
if (mask[MaskWidth - 1]) data[7:0] = read_byte(addr + i);
|
||||
else data[7:0] = 0;
|
||||
mask = mask << 1;
|
||||
end
|
||||
return data;
|
||||
endfunction
|
||||
|
||||
function void compare(mem_addr_t addr, mem_data_t act_data, mem_mask_t mask = '1);
|
||||
bit [7:0] byte_data;
|
||||
for (int i = 0; i < DataWidth / 8; i++) begin
|
||||
byte_data = act_data[7:0];
|
||||
if (mask[0]) begin
|
||||
compare_byte(addr + i, byte_data);
|
||||
end else begin
|
||||
`DV_CHECK_EQ(byte_data, 0,
|
||||
$sformatf("addr 0x%0h masked data aren't 0, mask 0x%0h", addr, mask))
|
||||
end
|
||||
act_data = act_data>> 8;
|
||||
mask = mask >> 1;
|
||||
end
|
||||
endfunction
|
||||
|
||||
endclass
|
Loading…
Add table
Add a link
Reference in a new issue