Skip to Content

Issuing concurrent READ/WRITE accesses to the same register on two physical interfaces using RAL.

Posted on  by  from the site Verification Martial Arts
Currently, RAL does not schedule multiple concurrent READ/WRITE accesses to the same register at the same time. RAL assumes all physical transactions to be atomic, i.e. a transaction is completed before the next cycle is started. Even if we try to do a parallel READ, RAL will block one of the two accesses and schedule it sequentially. This is to ensure that the accesses are not corrupted and also because of the fact that the main idea behind RAL is in abstracting accesses to the registers. However, in specific cases, there might be a verification requirement to create specific corner cases on the buses. A typical corner case to check parallel access to a shared register would be as shown in the code snippet below, Sample code : fork /* READ the CONTROL_REG via the APB interface */ env.ral_model.blk_inst.CONTROL_REG.read(status, data , , "APB"); /* Read the CONTROL_REG via the AHB interface */ env.ral_model.blk_inst.CONTROL_REG.read(status, data , , "AHB"); join Our intention here is to query the control register from two different domains "APB" & "AHB" in parallel or write through one interface and do a read access through another. But as already mentioned, a controlling semaphore mechanism tied to each register will sequentially schedule the above two accesses. To create such corner cases we can use the RAL proxy transactor with "vmm_ral_access::read/write()" which is not going be blocked as the semaphore resides in the register. The code below illustrates how we can do this. Sample code : fork /* READ the CONTROL_REG via the APB interface */ env.ral.read(status, env.ral_model.blk_inst.CONTROL_REG.get_address_in_system("APB"), data, 32, "APB"); /* READ the CONTROL_REG via the AHB interface */ env.ral.read(status, env.ral_model.blk_inst.CONTROL_REG.get_address_in_system("AHB"), data, 32, "AHB"); join The "vmm_ral_reg::get_address_in_system()" method can be used here to generate the correct address corresponding to the domain of interest and the same can be passed with the "vmm_ral_access::read()/write()" task. We can also do the following: 1) Read CONTROL_REG through one of the interfaces using "env.ral_model.blk_inst.CONTROL_REG.read()" & 2) Read the same register via vmm_ral_access::read() through the other interface as illustrated in the sample code below. Sample code : fork /* READ the CONTROL_REG via the APB interface */ env.ral_model.blk_inst.CONTROL_REG.read(status, data , , "APB"); /* READ the CONTROL_REG via the AHB interface */ env.ral.read(status, env.ral_model.blk_inst.CONTROL_REG.get_address_in_system("AHB"), data, 32, "AHB"); join Because the semaphore is in the register, the access through the proxy transactor is not going to be blocked. Also, if the DUT and physical transactor supports pipelined read/write accesses, the generic transactions can also be executed concurrently. You must first enable this capability by defining the compile time macro, VMM_RAL_PIPELINED_ACCESS.
S. Varun
Currently, RAL does not schedule multiple concurrent READ/WRITE accesses to the same register at the same time. RAL assumes all physical transactions to be atomic, i.e. a transaction is completed before the next cycle is started. Even if we try to do a parallel READ, RAL will block one of the two accesses and schedule it sequentially. This is to ensure that the accesses are not corrupted and also because of the fact that the main idea behind RAL is in abstracting accesses to the registers. However, in specific cases, there might be a verification requirement to create specific corner cases on the buses. A typical corner case to check parallel access to a shared register would be as shown in the code snippet below, Sample code : fork /* READ the CONTROL_REG via the APB interface */ env.ral_model.blk_inst.CONTROL_REG.read(status, data , , "APB"); /* Read the CONTROL_REG via the AHB interface */ env.ral_model.blk_inst.CONTROL_REG.read(status, data , , "AHB"); join Our intention here is to query the control register from two different domains "APB" & "AHB" in parallel or write through one interface and do a read access through another. But as already mentioned, a controlling semaphore mechanism tied to each register will sequentially schedule the above two accesses. To create such corner cases we can use the RAL proxy transactor with "vmm_ral_access::read/write()" which is not going be blocked as the semaphore resides in the register. The code below illustrates how we can do this. Sample code : fork /* READ the CONTROL_REG via the APB interface */ env.ral.read(status, env.ral_model.blk_inst.CONTROL_REG.get_address_in_system("APB"), data, 32, "APB"); /* READ the CONTROL_REG via the AHB interface */ env.ral.read(status, env.ral_model.blk_inst.CONTROL_REG.get_address_in_system("AHB"), data, 32, "AHB"); join The "vmm_ral_reg::get_address_in_system()" method can be used here to generate the correct address corresponding to the domain of interest and the same can be passed with the "vmm_ral_access::read()/write()" task. We can also do the following: 1) Read CONTROL_REG through one of the interfaces using "env.ral_model.blk_inst.CONTROL_REG.read()" & 2) Read the same register via vmm_ral_access::read() through the other interface as illustrated in the sample code below. Sample code : fork /* READ the CONTROL_REG via the APB interface */ env.ral_model.blk_inst.CONTROL_REG.read(status, data , , "APB"); /* READ the CONTROL_REG via the AHB interface */ env.ral.read(status, env.ral_model.blk_inst.CONTROL_REG.get_address_in_system("AHB"), data, 32, "AHB"); join Because the semaphore is in the register, the access through the proxy transactor is not going to be blocked. Also, if the DUT and physical transactor supports pipelined read/write accesses, the generic transactions can also be executed concurrently. You must first enable this capability by defining the compile time macro, VMM_RAL_PIPELINED_ACCESS.
Syndicate content