UVM provides several command line utils to change config. Two of these command line knobs are set_config_int and set_config_string. This is a deepdive into how they work.

Starting with src/base/uvm_root.svh, where m_do_config_settings is called in the build_phase of the uvm_root.

function void uvm_root::build_phase(uvm_phase phase);

  super.build_phase(phase);

  m_set_cl_msg_args();

  m_do_verbosity_settings();
  m_do_timeout_settings();
  m_do_factory_settings();
  m_do_config_settings();
  m_do_max_quit_settings();
  m_do_dump_args();

endfunction

In the same file, m_do_config_settings matches command line option with uvm_set_config_int and uvm_set_config_string and call m_process_config with is_bitargument to set to 1 with int.

function void uvm_root::m_do_config_settings();
  string args[$];

  void'(clp.get_arg_matches("/^\\+(UVM_SET_CONFIG_INT|uvm_set_config_int)=/",args));
  foreach(args[i]) begin
    m_process_config(args[i].substr(20, args[i].len()-1), 1);
  end
  void'(clp.get_arg_matches("/^\\+(UVM_SET_CONFIG_STRING|uvm_set_config_string)=/",args));
  foreach(args[i]) begin
    m_process_config(args[i].substr(23, args[i].len()-1), 0);
  end
endfunction

in m_process_config, the full string is split into 3 parts (path, config name, value). and it calls the set_config_int or set_config_string API from the m_uvm_top (that would be component).

function void uvm_root::m_process_config(string cfg, bit is_int);
  uvm_bitstream_t v;
  string split_val[$];
  uvm_root m_uvm_top = uvm_root::get();

  uvm_split_string(cfg, ",", split_val);

  if(is_int) begin
    if(split_val[2].len() > 2) begin
      string base, extval;
      base = split_val[2].substr(0,1);
      extval = split_val[2].substr(2,split_val[2].len()-1);
      case(base)
        "'b" : v = extval.atobin();
        "0b" : v = extval.atobin();
        "'o" : v = extval.atooct();
        "'d" : v = extval.atoi();
        "'h" : v = extval.atohex();
        "'x" : v = extval.atohex();
        "0x" : v = extval.atohex();
        default : v = split_val[2].atoi();
      endcase
    end
    else begin
      v = split_val[2].atoi();
    end
    uvm_report_info("UVM_CMDLINE_PROC", {"Applying config setting from the command line: +uvm_set_config_int=", cfg}, UVM_NONE);
    m_uvm_top.set_config_int(split_val[0], split_val[1], v);
  end
  else begin
    uvm_report_info("UVM_CMDLINE_PROC", {"Applying config setting from the command line: +uvm_set_config_string=", cfg}, UVM_NONE);
    m_uvm_top.set_config_string(split_val[0], split_val[1], split_val[2]);
  end

So, we jump to uvm_component.svh and we can see the actual call to config_db::set. Well, the shorthand typedef used there but you get the idea.

typedef uvm_config_db#(uvm_bitstream_t) uvm_config_int;

function void uvm_component::set_config_int(string inst_name,
                                           string field_name,
                                           uvm_bitstream_t value);

  uvm_config_int::set(this, inst_name, field_name, value);
endfunction

fin.