Uvm_mem model otp memory

class mem_otp_main extends uvm_mem;
    `uvm_object_utils(mem_otp_main)
    function new(string name = "mem_otp_main");
        super.new(name, 4096, 32, "RW", UVM_NO_COVERAGE);
    endfunction : new
endclass : mem_otp_main

class mem_otp_info extends uvm_mem;
    `uvm_object_utils(mem_otp_info)
    function new(string name = "mem_otp_info ");
        super.new(name, 21, 32, "RW", UVM_NO_COVERAGE);
    endfunction : new
endclass : mem_otp_info

class mem_otp extends uvm_reg_block;
    string otp_mem_path = "xxxx.xxxx.u_otp"
    rand mem_otp_main otp_main;
    rand mem_otp_info otp_info;

    `uvm_object_utils(mem_otp)
    function new(string name = "mem_otp ");
        super.new(name, UVM_NO_COVERAGE);
    endfunction : new
    function void build();
        default_map = create_map("", 'h0, 4, UVM_LITTLE_ENDIAN);
        otp_main = mem_otp_main::type_id::create("otp_main", this);
        otp_main.configure(this, otp_mem_path);
        otp_info= mem_otp_info::type_id::create("otp_info", this);
        otp_info.configure(this, otp_mem_path);
        default_map.add_mem(otp_main, 32'h0, "RW");
       default_map.add_mem(otp_info, 32'h0200_6000, "RW");
    endfunction
endclass : mem_otp 

as described in the above code, i am currently using uvm_mem to model two blocks of OTP. the main block is organized as 6K by 32bits. the infoblock is organized as 32 by 32bits. now i can use the frontdoor to access the OTP, but how should i acess OTP through the backdoor, because the main block and info block share a two dimensional array in the RTL model, the index of main block from 0 to 4095, the index of info block from 4096 to 4127, so how should i add the hdl path