• Content count

  • Joined

  • Last visited

About karandeep963

  • Rank
    Advanced Member

Profile Information

  • Gender
  • Location
    New Delhi
  1. 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
  2. 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
  3. 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.
  4. 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.
  5. 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.
  6. 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
  7. 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
  8. Great Many Thanks Tudor !!! I will try implementing this way.
  9. 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.
  10. 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);
  11. 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.
  12. 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
  13. 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
  14. Indeed !! Agreed. Thanks Tudor for quick response.
  15. 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 !!