sometimes we should use "disable fork" instead of "disable block_name"

A disable named block statement stops the execution of all blocks with that same name in all threads, which probably causes unexpected behavior.

Specific to this test, the “disable PM_LINK_WAIT_USB2_L1” statement will stops all active threads of PM_LINK_WAIT_USB2_L1 blocks, even if these PM_LINK_WAIT_USB2_L1 blocks are in different sequences.

Below I list the process of this issue.

1. In sequence “fch_usb_multi_port_trans_seqs”, sequence “fch_usb_lpm_trans_seqs” was called twice for each Port.

       //Start transfers for devices

        for(int dn=0;dn<number_of_device;dn++) begin

            automatic int j=dn;

            fork

                begin

                    for(int k=0;k<2;k++)   begin

                       usb_lpm_trans_seqs[j].otg_xhc_device_transfer= otg_xhc_device_transfer[j];

                       usb_lpm_trans_seqs[j].start(p_sequencer, this);

                    end

                end

            join_none

        end

 

2. In sequence “fch_usb_lpm_trans_seqs”, we need to read register PORTSC_20 to check whether Port is in L1 LPM state.

       //Enter low power

        reg_port_num = otg_xhc_device_transfer.device_cfg.port_number;

        if( pm_controller.pm_link_state == fch_otg_pm_controller::U1_L1 ||

            pm_controller.pm_link_state == fch_otg_pm_controller::U2_L1 ) begin

            fork : PM_LINK_WAIT_USB2_L1

                begin

                do begin

                    #5us;

                    expected_pm_link_state = 4'd2;

                    uvm_ext_fd_reg_access(`uvm_ext_fileline,RD,"dwc_usb3_reg","PORTSC_20",reg_data, reg_port_num);

                end while(reg_data[8:5] != 4'd2);

                end

                begin

                    if(otg_xhc_device_transfer.device_cfg.connected_bus_speed == svt_usb_types::LS) begin

                    #3500us;

                    end else if(otg_xhc_device_transfer.device_cfg.connected_bus_speed == svt_usb_types::FS) begin

                    #2500us;

                    end else begin

                    #500us;

                    end

                    `uvm_fatal(get_type_name(), $psprintf("PM: Link, waiting for USB2.0 L1 failed for port %0d", otg_xhc_device_transfer.device_cfg.port_number));

                end

            join_any

            disable PM_LINK_WAIT_USB2_L1;

            `uvm_info(get_type_name(), $psprintf("PM: Link, Port %0d is L1", otg_xhc_device_transfer.device_cfg.port_number), UVM_LOW);

        end

 

3. below waveform snapshot,

At #T1, usb_lpm_trans_seqs_0 read register PORTSC_20, and the RDATA is 32’h603

At #T2, usb_lpm_trans_seqs_1 read register PORTSC_20, and the RDATA is 32’h643.

That is, Port0 is in L1 state, and Port1 is not.

4. However, The sequence mistakenly checked the Port0 and Port1 were both in L1 state, which was reported in below log.

posted on 2016-11-18 14:00  jyaray  阅读(352)  评论(0编辑  收藏  举报

导航