Search the Community
Showing results for tags 'Backdoor'.
-
Hi there IPXACT needs to capture array of registers properly in a design. Currently there is only one tag ''spirit:dim" to represent an array of registers. This does not enable us to capture an array of register effectively. Consider the following cases: 1. An array of registers can be one dimensional with each element offset by offset address 0x10. 2. An Array of multidimensional registers something like this: register_1[0][0] -> 0x0 register_1[0][1] -> 0x4 register_1[1][0] -> 0x10 register_1[1][1] -> 0x14 ... likewise Is there any way to capture just the address relationship to an array instance within IP-XACT XML tags? (Without using vendorExtensions tag?) We have not been able to capture the above said information inside IPXACT XML.(using only IP-XACT tags) Requesting thoughts regarding the same. Best regards Balasubramanian G
-
I recently came upon an issue where attempting to write a memory via a backdoor yields a warning similar to the following: "reporter [RegModel] Memory 'tst_reg_blk.test_mem' is not contained within map 'Backdoor' (called from get_access())" In addition to the warning, it appears that due rw.map being overwritten (as explained in the second link), Read-Only memories can be written to via the backdoor, since get_access end up returning the default value of "RW". This appears to be in conflict with the Spec: Researching this warning turned up a couple prior forum posts from 2014: http://forums.accellera.org/topic/2104-question-about-backdoor-map/ http://forums.accellera.org/topic/2107-problem-with-backdoor-access-to-uvm_mem/ Neither of which had an associated answer. I came up with a test case to reproduce the warning: //####################################################################### // Backdoor accesses to a UVM_MEM that is a member of more than 1 map // causes a UVM_WARNING that that the memory is not contained within // the 'Backdoor' register map. // // This appears to happen due to the uvm_mem::Xcheck_accessX call in // uvm_mem::do_write, which replaces rw.map with the pseudo-map 'Backdoor'. // This replacement precedes the get_access(rw.map) call later in do_write. // The warning is generated when map membership is checked in get_local_map // which is called from get_access in the case that there is > 1 maps to // which the memory belongs. // // Below is a test case that reproduces the warning, as well as a workaround // that replaces the overwritten map (if WORKAROUND is defined). //####################################################################### package test_pkg; import uvm_pkg::*; `include "uvm_macros.svh" typedef class basic_test; typedef class test_env; typedef class test_reg_block; typedef class test_mem_class; //######################################### // Test //######################################### class basic_test extends uvm_test; test_env env; `uvm_component_utils(basic_test) //---- New Function ---- function new(string name = "basic_test", uvm_component parent); super.new(name, parent); endfunction : new //---- Build Phase ---- function void build_phase(uvm_phase phase); super.build_phase(phase); env = test_env::type_id::create("env", this); endfunction //---- Run Phase ---- virtual task run_phase(uvm_phase phase); uvm_reg_data_t data = 'hA5; uvm_reg_addr_t offset = 'h0000; uvm_status_e status; phase.raise_objection(this, "Starting Test"); `uvm_info(get_type_name(), "Got into Test Run_Phase.", UVM_LOW) `uvm_info(get_type_name(), $sformatf("Writing 0x%h.", data), UVM_LOW) //This causes a warning if WORKAROUND is not defined env.tst_reg_blk.test_mem.write(.status(status), .offset(offset), .value(data), .path(UVM_BACKDOOR), .map(env.tst_reg_blk.test_reg_map), .parent(null), .prior(-1), .extension(null), .fname(""), .lineno(0)); data = 'h0; //Warning does not occur on read env.tst_reg_blk.test_mem.read( .status(status), .offset(offset), .value(data), .path(UVM_BACKDOOR), .map(env.tst_reg_blk.test_reg_map), .parent(null), .prior(-1), .extension(null), .fname(""), .lineno(0)); `uvm_info(get_type_name(), $sformatf("Read 0x%h.", data), UVM_LOW) phase.drop_objection(this, "Test Is Done"); endtask : run_phase endclass //######################################### // Basic Environment //######################################### class test_env extends uvm_env; test_reg_block tst_reg_blk; `uvm_component_utils(test_env) //---- New Function ---- function new(input string name, input uvm_component parent=null); super.new(name,parent); endfunction //---- Build Phase ---- function void build_phase(uvm_phase phase); super.build_phase(phase); tst_reg_blk = test_reg_block::type_id::create("tst_reg_blk"); tst_reg_blk.configure(); tst_reg_blk.setup(); tst_reg_blk.set_hdl_path_root("test_tb"); endfunction : build_phase endclass //######################################### // Register Block Class //######################################### class test_reg_block extends uvm_reg_block; uvm_reg_map test_reg_map; uvm_reg_map test_reg_map_2; test_mem_class test_mem; `uvm_object_utils(test_reg_block) //---- New Function ---- function new(input string name="test_reg_block"); super.new(name); endfunction // new //Create Map, Add/Configure Memory, Lock Model function void setup(); test_reg_map = create_map("test_reg_map", 'h00000000, 4, UVM_LITTLE_ENDIAN, .byte_addressing(0)); test_reg_map_2 = create_map("test_reg_map", 'h00000000, 4, UVM_LITTLE_ENDIAN, .byte_addressing(0)); test_mem = test_mem_class::type_id::create("test_mem", , get_full_name()); test_mem.configure(this, "rtl_mem"); test_reg_map.add_mem( .mem(test_mem), .offset (32'h00000000), .rights ("RO"), .unmapped (0)); test_reg_map_2.add_mem( .mem(test_mem), .offset (32'h00000000), .rights ("RO"), .unmapped (0)); this.lock_model(); endfunction // setup endclass //######################################### // Register Block Class //######################################### class test_mem_class extends uvm_mem; `uvm_object_utils(test_mem_class) //---- New Function ---- function new(input string name="test_mem_class"); super.new(.name(name), .size(16), .n_bits(8), .access("RW"), .has_coverage(UVM_NO_COVERAGE)); endfunction // new //---- Bug Workaround ---- // Override the do_write task grab a local copy of the map. // Then override pre_write (which occurs after Xcheck_accessX) // to reassign the map with the local copy in the case of a // backdoor access. // // An actual fix would involve changing the behaviour of // Xcheck_accessX, which is non-virtual. `ifdef WORKAROUND protected uvm_reg_map backup_map; virtual task do_write (uvm_reg_item rw); backup_map = rw.map; super.do_write(rw); endtask virtual task pre_write (uvm_reg_item rw); super.pre_write(rw); if(rw.path == UVM_BACKDOOR) begin if(backup_map == null) rw.map = rw.local_map; else rw.map = backup_map; end endtask `endif endclass endpackage : test_pkg //######################################### // Basic TB //######################################### module test_tb(); import uvm_pkg::*; import test_pkg::*; `include "uvm_macros.svh" reg [7:0] rtl_mem [16]; initial run_test("basic_test"); endmodule I was able to come up with a work-around, but I feel that I am missing something. What is the actual purpose of uvm_reg_map::backdoor()? What is it's intended use case? Given that it has no parent block (thus not allowing memories or registers to be added), I do not know how it could be used. Thank you in advance for considering my question. //----------------- Edit ------------------------ I realized after the fact that this is a pre-IEEE issue. I Don't know if the topic can be moved to the correct forum. However, the question still stands; what is the intended purpose of the Backdoor pseudo-map?
-
Hi all, There is one register model such as this: class R_r extends uvm_reg; uvm_reg_field vaule; ... endclass : R_r class A_R_file extends uvm_reg_file; R_r R; ... endclass : A_R_file class R_model extends uvm_reg_block; A_R_file R_f; ... endclass : R_model class my_r_seq extends uvm_reg_sequence; R_model regmodel; ... write_reg(regmodel.R_f.R, status, wdata); peek_reg (regmodel.R_f.R, status, rdata); ... endclass : my_r_seq R_r is write-only, when reading R_r via backdoor as above, VCS reports such an error. UVM_ERROR /EDA_Tools/synopsys/vcs1209/etc/uvm-1.1/uvm-1.1d/src/reg/uvm_reg_block.svh(2049) @ 406000: reporter [RegModel] Block does not have hdl path defined for abstraction 'RTL' UVM_ERROR: get: unable to locate hdl path R_f.R Either the name is incorrect, or you may not have PLI/ACC visibility to that name The VCS reports that "unable to locate hdl path", but I have used configure() function to configure the hdl path in class A_R_file and class R_model. Did anybody meet the issue?
-
Hi, I'm trying to perform backdoor access to uvm_mem. For some reason, the Xcheck_accessX function in uvm_mem, override my map with pseudo map. From this function: rw.map = uvm_reg_map::backdoor(); From uvm_reg_map: // Function: backdoor // Return the backdoor pseudo-map singleton // // This pseudo-map is used to specify or configure the backdoor // instead of a real address map. // I need an important data from my map (the uvm_mem base address). why to override it? How can I overcome this? Thanks, Dror
-
Hi there I couldn't find enough information about capturing whitebox information with respect to a register defined in IP-XACT standard. Could this be done somehow? The closest that could be found was WHITEBOX information with respect to models.(not registers) Though the register definition can be captured in IP-XACT XML, there isn't proper way to capture RTL implementation of a register in IP-XACT. Capturing RTL implementation of a register in IP-XACT XML would enable us to stitch UVM_REG backdoor access. (without vendorExtensions) We feel the urge/need to enhance IP-XACT standard regarding the same. Requesting thoughts regarding the same. Best regards Balasubramanian G
-
Hi Guys, I am using UVM Register model to mimmick RTL's register implementation. Some registers are not implemented in RTL which are going to be connected to output port of some other module. I have got a HDL path of register as an output port declaration of some module. Something like: The HDL path is: "tb_top.dut_u.interrupt_module_u.o_ext_interrupt" o_ext_interrupt is declared as output port inside interrupt_module, which is not connected to any other wire or register. Can this output port's value be changed by writing to it via UVM BACKDOOR ? I am using following API: register_name.write(status,data,UVM_BACKDOOR,default_map); I dont see any change in value in the register. I think it is happening because the destination (o_ext_interrupt) is output of the module. I am using Cadence's simulator: irun. Please help if anyone is aware of such issue. Regards, Vismay.
- 1 reply
-
- UVM
- Register Model
-
(and 2 more)
Tagged with:
-
Backdoor read\write to a register
Rina301 posted a topic in UVM (Pre-IEEE) Methodology and BCL Forum
Hi, Please help with an issue about backdoor read\write to a register. Is it going to be fixed? When doing backdoor write\read to a register – the code (uvm_reg) uses the default map instead of the map the user gave in the write\read register operation: A. do_write gets rw with the correct map that the user wanted – rw.map. B. When doing backdoor write (1 below) , XpredictX (3 below) is called with rw.local_map (=null). get_access with null map is actually default map. C. Even If XpredictX was called with rw.map – it should make many warnings no matter what is the default map\which map we gave the write. This is because in the do_write, Xcheck_accessX (2 below) is changing rw.map to “Backdoor” – empty map which doesn’t contain any regs. ------------------------------------------------------------------------------------------------------------------------- 1. task uvm_reg::do_write (uvm_reg_item rw); -> with the user specified map - rw.map … if (!Xcheck_accessX(rw,map_info,"write()")) (see Xcheck_accessX below ) return; … // EXECUTE WRITE... case (rw.path) // ...VIA USER BACKDOOR UVM_BACKDOOR: begin .. begin foreach (m_fields) begin uvm_reg_data_t field_val; int lsb = m_fields.get_lsb_pos(); int sz = m_fields.get_n_bits(); field_val = m_fields.XpredictX((rw.value[0] >> lsb) & ((1<<sz)-1), (value >> lsb) & ((1<<sz)-1), rw.local_map); -> local map is null – see XpredictX below …. endtask: do_write ------------------------------------------------------------------------------------------------------------------------------------ 2. function bit uvm_reg::Xcheck_accessX (input uvm_reg_item rw, ->with the user specified map output uvm_reg_map_info map_info, input string caller); … if (rw.path == UVM_BACKDOOR) begin if (get_backdoor() == null && !has_hdl_path()) begin `uvm_warning("RegModel", {"No backdoor access available for register '",get_full_name(), "' . Using frontdoor instead."}) rw.path = UVM_FRONTDOOR; end else rw.map = uvm_reg_map::backdoor(); -> rw map is changed to “Backdoor”, local map is not calculated (for FRONTDOOR it is – below) end if (rw.path != UVM_BACKDOOR) begin rw.local_map = get_local_map(rw.map,caller); … return 1; endfunction ------------------------------------------------------------------------------------------------------------- 3. function uvm_reg_data_t uvm_reg_field::XpredictX (uvm_reg_data_t cur_val, uvm_reg_data_t wr_val, uvm_reg_map map); -> map is null uvm_reg_data_t mask = ('b1 << m_size)-1; case (get_access(map)) -> get access is performed with null map = get access is performed without giving a map and it is using the default map instead of the map that the user specified in the write operation "RO": return cur_val; "RW": return wr_val; … ------------------------------------------------------------------------------------------------------------- -
The issue I have is the register model has multiple registers of different names but the fields within the registers are named the same. The register model is generated by a tool so getting changes made will take some time and I need a work around. I have a lot of registers so this is a big problem. class reg_0 extends uvm_reg; rand uvm_reg_field x; rand uvm_reg_field y; ...... endclass class reg_1 extends uvm_reg; rand uvm_reg_field x; rand uvm_reg_field y; ...... endclass I need to be able to access the fields in my scoreboard. The problem is the field is not associated to the register so I can't simply call peek on x without associating it with the correct register. Is there a way to associate the register name with the field name and then call peek without hard coding the call to peek? I am using get_registers() and get_fields() to load my queues. Is there a way to get the registers and the fields for that register instead of one or the other? Perhaps I have missed something in the reference manual. reg_fields.peek(status,reg_field_data);