Sharing multiple parametrized typedefs across multiple classes

I wanted to make a class-based memory model (to be later integrated into UVM testbench). It had to be highly configurable through multiple parameters. The first approach was to make it through a parameterized class:


class memory_model #(
    parameter int DATA= 32,
    parameter int ADDR = 32,
    ...
    ) extends uvm_object;

    bit [bit [DATA-1 :0]] mem [bit [ADDR-1 :0]];
    ....

Now, being lazy as I am I found it a bit tedious to have to write bit [ADDR-1 :0], bit [DATA-1 :0], etc., every time in the same class. So I changed the class to this:


class memory_model #(
    parameter int DATA= 32,
    parameter int ADDR = 32,
    ...
    ) extends uvm_object;

    typedef bit [DATA-1 :0] mem_data_t;
    typedef bit [ADDR-1 :0] mem_addr_t;

    bit [mem_data_t] mem [mem_addr_t];
    ....

I then realized that I would need to use these types later across other related classes, Now the final form of my class is as follows:


class memory_config#(
    parameter int DATA= 32,
    parameter int ADDR = 32,
    ...
    ) extends config_base; // config_base extends uvm_object
    typedef bit [DATA-1 :0] mem_data_t;
    typedef bit [ADDR-1 :0] mem_addr_t;
....

class memory_model extends uvm_object;
    
    config_base mem_cfg;

    bit [mem_cfg::mem_data_t] mem [mem_cfg::mem_addr_t];
    ....

My question is this the best way to go, or is there a better pattern to follow? And how can I improve this model?

In reply to OYounis:

Your approach of using typedefs to define types based on the configuration parameters is a good way to make your code more readable and maintainable. It encapsulates the details of the data and address types within your memory model, making it easier to understand and modify. This also enhances configurability, as changes to the memory width or address width only need to be made in one place.

Here are a few additional suggestions to further improve and refine your memory model:

Separation of Concerns:

Consider separating the configuration class (memory_config) from the actual memory model class (memory_model). This can enhance modularity and make each class more focused on its specific responsibilities.
memory_config can handle all configuration-related parameters and typedefs, while memory_model can focus on implementing memory-specific functionality.
Parameterized Memory Model:

If your memory model will have additional features or behaviors that depend on configuration parameters, you can continue to use parameterization in memory_model.
For example, if the memory model has configurable behaviors like pipelining, burst mode, or other features, you can use additional parameters and conditional logic.
Use Enums for Read/Write Operations:

Consider using enums to represent different read and write operations (e.g., READ, WRITE) to make your code more self-documenting and improve readability.
You can define an enum in memory_model or a separate file if it’s reused across multiple classes.
Here’s an example illustrating some of these suggestions:

class memory_config #(
    parameter int DATA = 32,
    parameter int ADDR = 32
) extends config_base;
    typedef bit [DATA-1:0] mem_data_t;
    typedef bit [ADDR-1:0] mem_addr_t;
endclass

class memory_model #(type CONFIG = memory_config) extends uvm_object;
    typedef CONFIG::mem_data_t mem_data_t;
    typedef CONFIG::mem_addr_t mem_addr_t;

    config_base mem_cfg;

    bit [mem_data_t] mem [mem_addr_t];

    // Additional features and behaviors based on CONFIG parameters
    // ...

    // Example enum for read/write operations
    typedef enum logic [1:0] { READ, WRITE } mem_operation_t;

    function void perform_memory_operation(mem_operation_t op, mem_addr_t addr, mem_data_t data);
        // Implement memory operation based on the operation type
        // ...
    endfunction
endclass

By separating concerns and using typedefs and enums, your memory model becomes more modular, configurable, and easy to understand. It also provides a foundation for potential future enhancements or variations in the memory model behavior.


rahulvala@gmail.com
Freelancer/verification engineer
https://www.linkedin.com/in/rahulvala/