Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by karandeep963

  1. Great many thanks Tudor , I overlooked it . Also can you please also provide your expertise feedback on : Question 2: when we execute `uvm_do_on(eseq_inst[va],...) , so it creates an object and registers with factory. Does for every iteration it registers with factory the same name eseq_inst[va] instead of value eseq_inst[0]/eseq_inst[1]/eseq_inst[3]. as per UVM library : `uvm_do_on_with implicity calls `uvm_create which further calls create_item() as : { \ uvm_object_wrapper w_; \ w_ = SEQ_OR_ITEM.get_type(); \ $cast(SEQ_OR_ITEM , create_item(w_, SEQR, #SEQ_OR_ITEM));\ } Definition at line 146 of file uvm_sequence_defines.svh. while create_item has been defined as: protected function uvm_sequence_item create_item( uvm_object_wrapper type_var, uvm_sequencer_base l_sequencer, string name )
  2. class my_virtual_sequence extends uvm_sequence; `uvm_sequence_utils(my_virtual sequence,my_v_sequencer) exec_sequence eseq_inst[100]; ... virtual task body(); for(int i = 0 ; i <100 ; i++)begin fork automatic int var = i; // this is not allowed , getting compilation error `uvm_do_on(eseq_inst[var], p_sequencer.master_sequencer[var]) join_none end ..... some other piece of code ..... endtask: body endclass: my_virtual_sequence Hi , As per the above code, I wanted to parallely fire 100 transactions on 100 different masters_sequncers. Question 1: But it is not allowing to declare automatic variable before fork. what is alternative to this ? Also Question 2: when we execute `uvm_do_on(eseq_inst[var],...) , so it creates an object and registers with factory. Does for every iteration it registers with factory the same name eseq_inst[var] instead of value eseq_inst[0]/eseq_inst[1]/eseq_inst[3]. Since I checked UVM library and found `uvm_do_on_with implicity calls `uvm_create which further calls create_item() as : { \ uvm_object_wrapper w_; \ w_ = SEQ_OR_ITEM.get_type(); \ $cast(SEQ_OR_ITEM , create_item(w_, SEQR, #SEQ_OR_ITEM));\ } Definition at line 146 of file uvm_sequence_defines.svh. while create_item has been defined as: protected function uvm_sequence_item create_item( uvm_object_wrapper type_var, uvm_sequencer_base l_sequencer, string name ) So what is the work around to this if one wants to execute it with `uvm_do_* . May be using seq.start(sequncer) can be solution , but wandering if I can do it `uvm_do. Thanks
  3. Hi Folks, Interestingly today making some tweaks I faced a scenario with overrides. Suppose I add some variables in the extended class which are not present in the base class. Then I called the uvm_set_type_override from my top test. Interestingly I wanted to access those newly added variables in final_phase of some component , but during the simulator compile/elaboration phase it fails since the overrides are active during Simulation run-UVM_BUILD_PHASE. So my question is , if someone using some legacy code and wanted to update the stuff without re-writing again/or major changes , extended from base, then only overrides possible are those that will be active during simulation run , for an example , setting default sequence to driver with override. So there is no way we could leverage it. I am wandering , if TLM-GP extensions implementation may provide my some idea to do this. Any suggestions ??? If needed a code to see I saved the stuff http://www.edaplayground.com/x/2Ltr Line 156 is point of interest
  4. Hi , I have a case in which my DUT only toggles the valid bits of data output and doesn't change the rest of the bits. At the receiever side its state machine decides what all are the valid bits. DUT is purely based on couple of state machines. I have a C model for the same which does not have that state machines though it every time toggless all the data fields. For an example , lets say DUT transmits 0101 at N cycles and has to transmit only 0x04 at N+1th cycle so it again transmits 0101. since the LSB is not valid in this case. In case of model , it tries to follow the DUT and generated 0101 for Nth cycle and 0100 for N+1th cycles unlike DUT. There is SV-UVM scoreboard which compares both the transactions and creeps for this case. Now , I have few ideas in my mind. 1: I need to sit with designer and get to know the inside indepth working and re-write the stuff in scoreboard. 2: Other thing is I can do bitwise AND of DUT with MODEL output and compare with MODEL in scoreboard , but this will fail for the case in which DUT always respond with 0xFFFF. Any idea what can be the better approach in this case. Thanks, Karandeep
  5. One other way could be: Since binding of port can be possible with the components(which are supposed to be hierarchical members unlike sequence which associated during run-time). So you can create one port in your env and connect it to block_cfg_mngr import. Now in the sequence you might be already having the env pointer through config_db (if not set the port from env in the config_db) , get the pointer of env,port in your sequence and start accessing it. ///// Env Classs ///// class my_env extends uvm_env; uvm_tlm_b_initiator_socket #(uvm_tlm_gp) config_socket; function my_env::new(string name = "my_env", uvm_component parent = null); super.new(name, parent); // CONFIG config_socket = new ("config_socket",this); endfunction // build_phase: uvm_config_db #(uvm_tlm_b_initiator_socket)::set(this, "", "config", config_socket); //// Sequence Class /// class my_seq extends uvm_sequence(uvm_sequence_item) // CONFIG tlm block socket for configuration uvm_tlm_b_initiator_socket #(uvm_tlm_gp) bsocket; task body; // CONFIG GEtting Handle from env for config socket if(!uvm_config_db #(uvm_tlm_b_initiator_socket)::get(null,"uvm_test_top.m_env", "config", bsocket)) begin `uvm_error("CONFIG_DB_ERROR", "Could not find config") end // Use it the way you want bsocket.write(uvm_tlm_gp); endtask: body
  6. I think UNIQUE KEYWORD does well , I have used it with Synopsys VCS, a quick example ::-> http://www.edaplayground.com/x/6AHE Not sure about cadence incisive, sometime back raised CCR for enhancement for this feature , not sure whether it is available. But yes, this unique keyword does much beautification to my code.
  7. It can be done in two ways: 1. Use reg callbacks pre_predict/post_predict to update the values. http://forums.accellera.org/topic/5107-uvm-register-implimentation-for-same-register-with-different-instances/ will be help you in a better way. Thanks to Tudor Timi for his kind help !! 2. The other way would be overload your predictor to do this stuff.
  8. As far as I understand Chip Select(CSbar) is active low in nature , so its the masters responsibility to control/enable/disable it while the slave has to respond to the command input. Slave must not drive CSbar. Slave must be active on CSbar low and process the input command and do the needful.
  9. Though its late to answer I guess, here is one solution: Create two packets in your monitor as follow; class any_monitor extends uvm_monitor; // rest things task run_phase (uvm_phase phase); my_packet previous_packet = my_packet::type_id::create("previous_packet"); my_packet current_packet = my_packet::type_id::create("current_packet "); // Processing the transaction // Do the needful and before sending the packet through monitor analysis port make a local copy for it as // since we send the packet through analysis port in the end where we are all done with our processing , so upto here you have previous packet available $cast(previous_packet,current_packet ); analysis_port.write(current_packet ); // In this way you can make for more copies , even put these copies in fifo , do whatever flavor your want to implement endtask In the above way you can make for more copies , even put these copies in fifo , do whatever flavor your want to implement. Hope it will meet your requirements. Regards, Karandeep
  10. Let me try to understand the problem before proposing any solution. You wanted to access the 32bit and 64bit data-width registers via program bus whose datawidth 64 bits. In hardware we mimic such scenarios using byte_enable that decides the valid bytes in data_width and registers those are only 32bits valid fields implemented marked the rest with reserved bits. Same is done in the RAL as well , we only implement the valid fields for the register while non-implemented space treated as reserved. So while accessing the registers the respective values are updated. Let me take another example , Your RAL registers will be updated with what the data you received from monitor (in case of read)on the program bus, since the monitor mimics the program bus protocol so it will create a valid values in data-width using byte_enables. Now the transaction created by monitor would be passed to your RAL registers via reg_adapter(adheres two api's reg2bus and bus2reg) which further updates the desired/mirrored values as per the call. I might not be getting the right understanding to your question, in that case let me share my views about tlm extensions, that might connect you in better way. TLM extensions as far as I understand come with tlm_gp (TLM_GENERIC_PAYLOAD). TLM_GP in itself is enough to carry the required contents for valid memory mapped transactions as it contains : m_address m_data m_command m_streaming_width m_byte_enable_length extensions are optional part that is associated with your payload , by the word "Optional" I wanted to say that apart from above if you need some other information to be passed that can be send in extensions. The beauty is that if at the receiver/driver is looking for that extra information it will use it and if not that will be ignored simply, thus providing you the interoperability between those two driver using the same payload. I tried with my assumption, let me know your views. Regards, Karandeep
  11. Agreed !! But the problem is that there isn't any post_predict(...) hook defined for uvm_reg, do need to make n number of callbacks for n/4 registers. Scarifying the vertical reuse for sake of using single callback for n registers. Indeed at deep of my heart I was feeling it not a good way, Thanks for pointing. Now I will for sure try to find some other way out. Implementing this behavior in predictor will help ??? I will try to check this implementing at predictor level. Thanks for your valuable feedback.
  12. Thanks Tudor for sharing your thoughts, it really helps. Posting here the implementation, might be helpful of someone someday (provided better ways would always be there ) --------------------// CALLBACK IMPLEMENTATION //--------------------------- class my_cb extends uvm_reg_cbs; `uvm_object_utils(my_cb) virtual task post_write( uvm_reg_item rw); uvm_reg my_reg; uvm_reg rg; int unsigned offset_addr; if (!$cast(my_reg ,(rw.element))) begin //TODO: remove this once able to use get_offset() api with rw.element `uvm_error("WRONG_TYPE","Provided casting failed") return; end offset_addr = (my_reg.get_offset() & 'hFFF0); for(int i = offset_addr; i <= (offset_addr+'hC); i= i+4)begin rg = rw.map.get_reg_by_offset('h0000+i, (rw.kind == UVM_READ)); if (rg == null) begin `uvm_fatal("REG_NULL",$sformatf("Unable to reg by offset = 0x%8x : called from %s",('h0000+i), get_type_name() )) end rg.predict(my_reg.get_mirrored_value()); // Updating the mirror values for all the four reg end endtask:post_write endclass:my_cb ----------------------// IN REG BLOCK //--------------------- virtual function void build(); my_cb cb_reg = new(); // Now create all registers REG1 = REG_1::type_id::create("REG_1", , get_full_name()); REG_1.configure(this, null, ""); REG_1.build(); // Similar for REG_2/REG_3/REG_4 uvm_reg_cb::add(REG_1, cb_reg); uvm_reg_cb::add(REG_2, cb_reg); uvm_reg_cb::add(REG_3, cb_reg); uvm_reg_cb::add(REG_4, cb_reg);
  13. Thanks Tudor !! You exactly hit the right place. Indeed registered callback to reg only. I think what I wanted to acheive would have to be done in other way. I wanted to implement "SHARED VALUE" registers which are at different address space in same map. Lets say I have 0x0 REG 1 --> Type RW 0x4 REG 2 --> Type W1S 0x8 REG 3 --> Type W1T 0xC REG 4 --> Type W1C Now any change(write) to any register should be reflected(read) same in all the four. For this reason I planned to make a callback, register that with all the four reg, any writeaccess to an anyone will trigger the same callback in which post_predict will update the desired value of all the four with the current updated(desired) value of accessed register. Can you please share thoughts what wud be the better way for this type of implementation. Thanks once again. Karandeep.
  14. Hi Tudor, Thanks for the above example, I am trying to implement the same but for different scenario. But I am stucking at a place that in my callback class post_predict is not called while I am reading/writing reg(with which callback is registered). I can see the prints from pre_write/post_write/pre_read/post_read. Can you please help me out where you suspect the issue. Thanks, Karandeep
  15. An example from LRM may help you out (just a suggestion): Generic coverage groups can be written by passing their traits as arguments to the constructor. For example: covergroup cg (ref int ra, input int low, int high ) @(posedge clk); coverpoint ra // sample variable passed by reference { bins good = { [low : high] }; bins bad[] = default; } endgroup ... int va, vb; cg c1 = new( va, 0, 50 ); // cover variable va in the range 0 to 50 cg c2 = new( vb, 120, 600 ); // cover variable vb in the range 120 to 600
  16. Couple of questions came to me while discussing this topic which I tried to answer as per my knowledge. Please post your comments/corrections for the following: 1) What register map normally define? -> complete range which includes valid and invalid register space. KS: Ideally register layer/map for UVM mimics only valid address registers , it doesn't mimics invalid/out-of bound register 2) What should be the data value of invalid address range, and who/how to defined? KS: The in-built test sequence(if made) will not check for data value. It will be used to make sure that the bus must not hang(bus may return garbage or error data if defined). It can be configured through config_db like we use in the case of “NO_REG_TEST” in built in sequences. 3) What should auto predictor will check, is it just the data OR error response too? -> because its normally convention that a target IP will give error response on every invalid access( we already know this). KS: This should be again CONFIG_DB controlled whether to validate error response or to ignore. 4) Assumption is normally target IP will error response, but what happen when IP is designed not to give response on any invalid request. So in this case will the register map/bus agent is configurable not to expect any response. KS: The error checking response can simply be bypassed through CONFIG_DB switch like what we do for “NO_REG_TEST” in built sequences there can be another "NO_ERROR_CHECK_REG_INVALID_TEST". 5) What happen when OOO(Out of order) response appeared on program bus. KS: This is difficult for me to answer but what I understand is Program Bus are generally in order buses. 6) Some pseudo code which define how invalid address range will work? KS: Template generation is under work !!
  17. I think here is the link which Tudor pointed ("There was an article on exactly this in an older edition of Verification Horizons"): http://s3.mentor.com/fv/verification-horizons-publication-february-2013.pdf
  18. Interesting discussion. I appreciate !! One thing I found most interesting from DVCON 2014 "Advancing system-level verification using UVM in SystemC" - Martin Barnasconi This makes me feel that at least we need to converge some where !!
  19. Hi , I would like to exchange the thoughts on built in sequences for register verification supports only accessing the valid registers. Why should we not also expect to put some transaction other than valid address so to verify that bus should not hang ? This is good thing and I think every verification engineer does himself in his verification setup. So I considered an important part this may be added to default UVM reg test seq library. As per my understanding this can be achieved in two ways: 1. Adding dummy register for invalid address range. --> so in this case built-in reg_test sequences will pick them up for access 2. Manually make the bus transaction by providing invalid address. 3. Better way(Suggestion) --> In the register layer it should calculate the lowest and highest offset and if user enables the invalid address check (either from CONFIG_DB or CONFIG_FILE) it should create the transaction in the invalid range. For 1 & 2 I have made the setup which is basically user effort. For point 3. I expect your views to make efforts further. Please suggest any better way if figured out !! Great Many Thanks for your replies. Please correct me if my assumptions/expectations are incorrect. Thanks, Karandeep
  20. Adding some thoughts , I am using this multi-language (UVM- SV-SC) TB in many projects and I feel its best method than anything. See your model not run on its own(as you think like DUT) in this case its not the RTL dont imagine it like RTL, it should ideally be supplied the request transaction when their is response from DUT. In this case your model will take a call and execute in zero time so you will be getting the updated response which should ideally be the same as that of RTL. There would be some grey areas such as when you have parallel accesses, for an instance one bus is reading/writing FIFO's and you are monitoring the status on other bus(register access) in that case you would probably need to modify your sequences in such a way that you should be monitoring the status after your vectors done. These sought of some grey areas will created if user doesn't think the overall scenarios carefully. Anyway Modeling is an art of imagination this is what I feel
  21. Many Thanks TUDOR and ALAN, That helps a lot. Thanks to Bryan's Posts as well. Indeed the tricks needed to use it !!
  • Create New...