C++ Register Modeling Framework

Some time ago we developed a lightweight register modeling framework, amiq_rm, similar with the uvm_reg and vr_ad libraries. We implemented amiq_rm in C++ such that we could seamlessly integrate it with both SystemC and C++-based projects.

Here are the main features of amiq_rm:

  • Simple and intuitive API (HTML documentation included)
  • You can group registers into register blocks
  • You can map registers to one or more address maps and create complex map hierarchies
  • You can define and instantiate fields with configurable name, reset value, size, attributes (e.g. R1C, RW, RO, etc.)
  • You can add custom field attributes
  • You can perform field operations: adding fields, getting and setting the value of a field
  • You can register callbacks that take place after/before the actual READ/WRITE operation (pre_access, post_access)
  • You can perform hierarchical searching of registers by name or by offset
  • You can easily integrate the register models with LT/AT SystemC protocol implementations
  • The library was tested using both unit tests and production use cases.
  • It is released under Apache License 2.0

This article is a step-by-step tutorial for modeling a set of registers using the amiq_rm library.

The Example

The example illustrates how to model several registers which are accessible by two different interfaces (See Fig. 1).

The Topology
Figure 1. The topology

Step 1. Download amiq_rm library

The example is part of amiq_rm library, which you can download from GitHub.

Step 2. Define the registers

Every register class should inherit amiq_rm_reg. You should add the register fields in its constructor.

//create a register class that models register local_id
class local_id_reg: public amiq_rm_reg {
public:
   local_id_reg(string my_name) : amiq_rm_reg(my_name) {
      //add a field for "local_id" register called "id"
      add_field(new amiq_rm_field("id", 0x00, 8, "RW"));
      add_field(new amiq_rm_field("reserved", 0x0, 4, "RO"));
   }
};

Step 3. Define a register block

A register block inherits amiq_rm_reg_block. It contains the entire set of registers and all the address maps required. You should add the registers to the corresponding address map in its constructor.


class amiq_rtr_reg_block: public amiq_rm_reg_block {
public:
   //handle for the local ID register
   local_id_reg local_id_h;

   // handle for the physical address map corresponding to UART interface 
   amiq_rm_physical_address_map uart_map;
   // handle for the physical address map corresponding to RTR interface
   amiq_rm_physical_address_map rtr_map;

   amiq_rtr_reg_block() : amiq_rm_reg_block("my_reg_block"), 
                          local_id_h("local_id"), uart_map("uart_map"), rtr_map("rtr_map") {
      //add register local_id to the UART address map, at offset 0x00
      uart_map.add_reg(local_id_h, 0x00);
      uart_map.build();
   }
};

Step 4. Access the registers

The registers can be accessed using the “write()” and the “read()” methods from the address map.


int main(int args, char * argv[]) {
   //do a write to local_id (register address 0x00) with data 0xFF
   reg_block.uart_map.write(0x00, 0xFF);

   //do a read from local_id (register address 0x00)
   pair data_with_status = reg_block.uart_map.read(0x00);

   return 0;
};

At this point all you need to do is to compile and run. The example package contains a Makefile that you can use as follows:

$> cd build
$> make -f makefile all
$> ./amiq_rm

Roadmap

We plan to extend the model’s functionality with the following:

  • add logic to make the register accesses thread safe
  • provide examples for integration with TLM-1.0/2.0 sockets (LT, AT models)
  • implement checks for overlapping addresses
  • implement a get_absolute_addresses() method for address map and registers – it requires to return a list of addresses and the paths to the register

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe to our newsletter

Do you want to be up to date with our latest articles?