Search the Community
Showing results for tags '::set'.
c4brian and I have messaged a bunch about ways to share data and access between elements in SV/UVM code. I put common functions/tasks/constants into a package, which I think is standard. I realize that absolute dot notation of accessing elements (i.e. variable12 = smthgA.smthgB.smthgC.variableXYZ;) is frowned upon as it is not good for reuse. So, the UVM presents the uvm_config_db to facilitate reuse and simplify connectivity across a hierarchy.**1 Many folks have (including c4brian, I believe) commented that they don't like how verbose it is to ::get from the config db and to check the return result. if (! uvm_config_db#(integer)::get(this,"hiccup","xyz_important_var", important_var) ) begin `uvm_fatal("ERROR,"important_var not found in config_db") end In a recent testbench, I've done the following. I probably need to review how the config component is supposed to be used. I am curious what others think. My setup: 1) Create an object to store common variables and handles. //This should be a singleton and serve as a central point for others to access global connections. Likely not a good style. Discuss. class xyz_config extends uvm_component; `uvm_component_utils(xyz_config) static xyz_env m_env; static id_state m_id_state; static delay_ctl m_delayctl; function new(string name="xyz_config", uvm_component parent=null); super.new(name, parent); endfunction set_env_handle(input xyz_env handle); m_env=handle; endfunction : set_env_handle ... 2) When something is created that other code might want to access, I set a handle to it in xyz_config. ex1: In the test class constructor (which is declared inside top), create the env and set a handle to it in the xyz_config. (Probably these actions should be done in the build_phase rather than the constructor.) class test_base extends uvm_test; `uvm_component_utils(test_base) xyz_env env; function new(string name = "test_base", uvm_component parent = null); super.new(name, parent); env = xyz_env::type_id::create("env",this); xyz_config::set_env_handle(env); ex2: In the env build_phase, I set handles to some objects which track data which is useful in many sequences and other code function void xyz_env::build_phase(uvm_phase phase); super.build_phase(phase); ... // Create Helper Structures m_id_state = id_state::type_id::create("m_id_state",this); xyz_config::set_id_state_handle(m_id_state); m_delayctl = delay_ctl::type_id::create("m_delayctl",this); xyz_config::set_delayctl_handle(m_delayctl); 3) Now, in various parts of the tb (such as from sequences), I can access xyz_config as a singleton, and access its handles (using . "dot" notation) to whatever data structures it was given access to. (I'm thinking now that those data structures should be in the scoreboard.) The dot notation is much more concise than declaring a variable and then performing a uvm_config_db ::get and checking the return value. //in seq, id_state which tracks system-state used to set transaction variable jhg_input_trans.state = xyz_config::m_id_state.get_jhg_state(.loopback(loopback), .fce_1(fce_1)); or //in virtual seq, a call is made that turns off any internal stallers (special stallers to alter congestion in the dut) xyz_config::m_env.turn_off_internal_stallers(); or //in scoreboard, as monitors send in transactions, it adjusts state info which is used by sequences to make legal input xyz_config::m_id_state.move_some_id(.note("fuf->xyz"), .syd(t.fuf_xyz_read_syd), .from_q(Q001), .to_q(Q111)); A benefit of this is that the user can more easily (from this line of code), see what is being accessed, rather than needing to rerun a test and dump config_db or grep thru a bunch of files to see who did the ::set. With regards to reuse, it seems to me that as long as the new tb (that wants to benefit from reuse), sets the handles in the _config properly, it is just as reuse-able. Probably, I am missing something. I've have a vague notion and have heard soft feedback that this style (which I feel is unique to me) is not good. Maybe I'm imagining this or exaggerating it in my mind. I bring it up here, in the event anyone has feedback or a good scolding to give. **1 Conceptually I've been taught to think of uvm_config_db as a "string"-accessible associative array, or a group of associative arrays; something like 'one for each datatype'. I'm not poking into the uvm base class here, but just voicing my understanding out-loud for comments. Conceptually, I think of uvm_config_db as operating as follows. A user specifies the data type that they want to store or get - which 'conceptually' selects which associative array to access. A user specifies a "string-name" which is the key into that associate array. A user reads or writes that associative array as follows. To write, they use ::set, specify a "string-name", and provide a value. To read, they use ::get, specify a "string-name", and provide a variable, into which the value stored at "string-name" will be copied. (Note: I've modified the code examples to shorten them, so may have introduced typos.)