hvgbl Posted August 8, 2014 Report Share Posted August 8, 2014 Hello Everyone. My question is I can write a register value, but cannot read the same value back. I can get the written value from register by get() method, but when i read the same value, i receive 0, "ZERO". Any solution for this one ? my register sequence is as follows. virtual task body(); uvm_status_e status; uvm_reg_data_t data; $display("\n\n\nTRANSACTION SEQ1 Starting....."); block_obj.reg2.write(status,'h05,UVM_FRONTDOOR,.parent(this)); #09; desired_value = block_obj.reg2.get(); $display($time,"(1)desired_value is %0h",desired_value); $display ($time,"\n\nSEQ READ START"); block_obj.reg2.read(status,data,UVM_FRONTDOOR,.parent(this)); $display ($time,"READ SEQ final data %h\n\n\n",data); desired_value = block_obj.reg2.get(); $display($time,"(2)desired_value is %0h",desired_value); endtask: body Quote Link to comment Share on other sites More sharing options...
tudor.timi Posted August 8, 2014 Report Share Posted August 8, 2014 Show us your register definition. Are you sure the register doesn't have only "WO" fields? Quote Link to comment Share on other sites More sharing options...
hvgbl Posted August 8, 2014 Author Report Share Posted August 8, 2014 My Register Class: My registers are of RW access policy. class my_register extends uvm_reg; `uvm_object_utils(my_register) rand uvm_reg_field pid; rand uvm_reg_field token; uvm_reg_field reserved; function new (string name = "my_register"); super.new (name, 8, UVM_NO_COVERAGE); endfunction: new virtual function void build(); pid = uvm_reg_field::type_id::create("pid"); token = uvm_reg_field::type_id::create("token"); reserved = uvm_reg_field::type_id::create("reserved"); pid.configure(.parent(this), .size(3), .lsb_pos(0), .access("RW"), .volatile(1), .reset(0), .has_reset(1), .is_rand(1), .individually_accessible(0)); token.configure(.parent(this), .size(3), .lsb_pos(3), .access("RW"), .volatile(1), .reset(0), .has_reset(1), .is_rand(1), .individually_accessible(0)); reserved.configure(.parent(this), .size(1), .lsb_pos(6), .access("RW"), .volatile(1), .reset(0), .has_reset(1), .is_rand(1), .individually_accessible(0)); endfunction: build endclass: my_register Quote Link to comment Share on other sites More sharing options...
tudor.timi Posted August 8, 2014 Report Share Posted August 8, 2014 When you add your register (or the block/reg_file that contains it) to the address map, did you by any chance add it as WO? Quote Link to comment Share on other sites More sharing options...
hvgbl Posted August 8, 2014 Author Report Share Posted August 8, 2014 Thankyou sir, But i have defined the registers as RW only. Still facing the problem. The issue i observed is that when i do write-read method. During read method, the bus2reg function is called twice, which overwrites my data. The last third line of below transcript provides me correct address and data.But the second call to bus2reg, overwrites my data and address. And when i use get() method to recheck the data, it will return the correct data stored in my register. :::Transcript::: 0REG2BUS rw,data = 9 at rw,addr = 20 // write sequence started. reg2bus called. # 10value of read_en is 0 // Driver driving the signals on the interface # 10value of write_en is 1 // Driver driving the signals on the interface # 10value of ADD is 20 // Driver driving the signals on the interface # 10value of write_data is 9 // Driver driving the signals on the interface # 10DUT - WR 09 @ 20 // Transaction executed on DUT # 15 mo - read_data is 00 // Monitor gets the previous value of DUT. # 15PRED - in write data 0000000000000000 | mypl data00 // Bus2Reg called once in write condition. # 19PRED - in write data 0000000000000000 | mypl data00 // Bus2Reg called 2nd time in write condition. # 20DUT - WR 09 @ 20 // As i have placed a #10 delay between write and read, the write will executed once again. # 25 mo - read_data is 00 # 25PRED - in write data 0000000000000000 | mypl data00 # 29 # # SEQ READ START // Read Sequence started # 29REG2BUS rw,data = 0 at rw,addr = 20 # 30value of read_en is 1 # 30value of write_en is 0 # 30value of ADD is 20 # 30value of write_data is 0 # 30DUT - RD 09 @ 20 # 35 mo - read_data is 09 # 35PRED - in read data 0000000000000009 | mypl data09 # 39PRED - in read data 0000000000000000 | mypl data00 # 39READ SEQ final data 0000000000000000 # :::Register Block Class::: virtual function void build(); $display("REG_BLOCK -- REG BLOCK BUILD STARTED"); reg1 = my_register::type_id::create("reg1"); reg1.build(); reg1.configure(this); reg2 = my_register::type_id::create("reg2"); reg2.build(); reg2.configure(this); my_reg_map = create_map (.name("my_reg_map"), .base_addr(8'h00), .n_bytes(4), .endian(UVM_LITTLE_ENDIAN)); $display("REG_BLOCK -- REG-MAP CREATED"); my_reg_map.add_reg(.rg(reg1), .offset(8'h10), .rights("RW")); $display("REG_BLOCK -- REG1 CREATED"); my_reg_map.add_reg(.rg(reg2), .offset(8'h20), .rights("RW")); $display("REG_BLOCK -- REG2 CREATED"); lock_model(); endfunction: build Quote Link to comment Share on other sites More sharing options...
Roman Posted August 11, 2014 Report Share Posted August 11, 2014 Hi, #1. when you call the UVM_REG.write, the bus2reg happens twice. It's correct. 1st happens on uvm_reg_map::do_bus_write (adapter.bus2reg(bus_rsp/req,rw_access) 2nd happens on uvm_reg_predictor::write( adapter.bus2reg(tr,rw) ---- when bus monitor broadcasts the bus transaction (write or read) to uvm_reg_predictor.bus_in, this function will be called and will update the RAL model. #2. Make sure your bus monitor connects to the uvm_reg_predictor.bus_in uvm_analysis_imp well. please also check if the read data is 0 or correct value on the bus of DUT. Try block_obj.reg2.get_mirrored_value(); to check the mirror value. Quote Link to comment Share on other sites More sharing options...
hvgbl Posted August 11, 2014 Author Report Share Posted August 11, 2014 Yes, sir. But you can see from transcript output, i have replied in previous post. The bus2reg called by monitor broadcast executes first. And it returns correct data. (Checked by placing display). Where as when bus2reg called by uvm_reg_map, executes last, and that does not provides correct data. The transcript output at time "35". 35 mo - read_data is 09 // Monitor Snoops the data and broadcast it. # 35PRED - in read data 0000000000000009 | mypl data09 // BUS2REG called by uvm_reg_predictor class, which return 09 value. # 39PRED - in read data 0000000000000000 | mypl data00 // BUS2REG called by uvm_reg_map, which DOES NOT RETURN ACTUAL (09) VALUE. # 39READ SEQ final data 0000000000000000 // Displaying actual data. The connections in environment class are as follows: function void connect_phase(uvm_phase phase); super.connect_phase(phase); block_obj.my_reg_map.set_sequencer(agt_obj.seqr_obj, adpt_obj); // block_obj -> register Block instance, my_reg_map -> register map instance. agt_obj.mon_obj.mon_ap.connect(predictor_obj.bus_in); // agt_obj -> agent class instance, mon_obj -> monitor class instance, mon_ap -> monitor analysis port. predictor_obj.map = block_obj.my_reg_map; predictor_obj.adapter = adpt_obj; //block_obj.my_reg_map.set_auto_predict(0); //block_obj.my_reg_map.set_check_on_read(0); endfunction: connect_phase Quote Link to comment Share on other sites More sharing options...
Roman Posted August 11, 2014 Report Share Posted August 11, 2014 do set_auto_predict(0) because you are using explicit prediction infrastructure. Quote Link to comment Share on other sites More sharing options...
hvgbl Posted August 11, 2014 Author Report Share Posted August 11, 2014 Sir, i also did with set_auto_predict(0).But still facing the issue. Quote Link to comment Share on other sites More sharing options...
hvgbl Posted August 12, 2014 Author Report Share Posted August 12, 2014 This POST IS FIX. In my driver, i had update the data field after a read transaction. Which reflects the BUS2REG. Thank you everyone, for your precious inputs. Quote Link to comment Share on other sites More sharing options...
tudor.timi Posted August 12, 2014 Report Share Posted August 12, 2014 What I found problematic was that he said he did set_auto_predict(0) and he still needed to update the item coming from the driver, because its value was used to update the register model. This might be interesting to debug by some UVM developer, maybe there's an issue in UVM behind it. Quote Link to comment Share on other sites More sharing options...
uwes Posted August 13, 2014 Report Share Posted August 13, 2014 hi, i think the answer is "simple" 1. the active path reg.read()->seqr->adapter->driver->adapter->seqr->reg.read()-end always needs that the driver supplies the final data and the adapter translates it. if your driver finishes the transaction before the transfer is complete (posted transactions, out of order, pipelined transactions, etc) OR doesnt provide the correct data then the result of the read() does not reflect the right value. there is no other way to return data to the caller than via this path. 2. the difference auto_predict() makes is that with auto_predict(1) the active path will update the shadow register while with auto_predict(0) some other instance needs to take care of that (monitor->predictor).in other words - auto-predict() has no influence of what data is being returned to the caller of a reg.read() call. 3. the adapters bus2reg and reg2bus should be kind of "inverse" - if they are not its likely that wrong data is provided, the wrong register updated with wrong data etc. /uwe Quote Link to comment Share on other sites More sharing options...
hvgbl Posted August 13, 2014 Author Report Share Posted August 13, 2014 Exactly you are right uwes. But my point of confusion was that, dont we have any other method to update the transaction packet ? I mean, INITIALLY my driver class contained a single task, which simple recieves the transaction and send it on iterface. I was not taking response from DUT. But as TIMI suggested, i added a logic which gets back the response from DUT. So now my DRIVER CLASS CODE IS AS FOLLOWS: virtual task drive_sig(my_packet drv_pkt); //Driving the signals on the interface. drv_intf.read_en <= drv_pkt.read_rq; drv_intf.write_en <= drv_pkt.write_rq; drv_intf.ip_add <= drv_pkt.add; drv_intf.write_data <= drv_pkt.write_data; #1; receive_data(); // Recieving transaction generated by DUT. endtask: drive_sig task receive_data(); if (drv_intf.read_en == 1) begin drv_pkt.read_data = drv_intf.read_data; end else drv_pkt.read_data = 'hff; endtask: receive_data So this do imply that, i have implemented MONITOR CLASS functionality in my DRIVER CLASS. For a single RAM DUT, it is OK to have such logic. But for a big design, do i have to implement whole Monitoring Logic (i.e. DUT's Output). uwes any words on above confusion ? Quote Link to comment Share on other sites More sharing options...
Ai_Ar Posted May 13, 2021 Report Share Posted May 13, 2021 On 8/11/2014 at 10:06 PM, hvgbl said: This POST IS FIX. In my driver, i had update the data field after a read transaction. Which reflects the BUS2REG. Thank you everyone, for your precious inputs. Hi, what do you mean? how is the data sent to the adapter's bus2reg function? Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.