diff --git a/.github/workflows/private-ci.yml b/.github/workflows/private-ci.yml index 0a8ad754a9..22430b0320 100644 --- a/.github/workflows/private-ci.yml +++ b/.github/workflows/private-ci.yml @@ -16,59 +16,23 @@ on: - "*" permissions: - statuses: write + contents: write # For repository dispatch jobs: trigger: name: Trigger Private CI runs-on: ubuntu-latest steps: - # Find a merge commit. We cannot use merge_commit_sha from context directly because - # mergeability check is asynchronous to pull_request_target trigger.. - - name: Find the merge commit - id: merge - if: github.event_name == 'pull_request_target' - uses: actions/github-script@v7 - with: - script: | - for (let i = 0; i <= 5; i++) { - const { data: pr } = await github.rest.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.issue.number, - }); - - if (i != 5 && pr.mergeable == null) { - console.log("Mergeability check in progress"); - await new Promise(r => setTimeout(r, 2000)); - continue; - } - - if (pr.mergeable) { - core.setOutput('merge_sha', pr.merge_commit_sha); - } else { - core.setFailed('Pull request is not mergeable'); - } - break; - } - - # Create pending statuses to block merge group and give indication before jobs are picked up. - - name: Create pending statuses + - name: Trigger Private CI run: | - gh api --method POST \ + PAYLOAD='"target":"${{ github.repository_owner }}/lowrisc-private-ci/master/ibex-private-ci.yml","sha":"${{ github.event.pull_request.head.sha || github.sha }}"' + if ${{ github.event_name == 'pull_request_target' }}; then + PAYLOAD+=',"pull_request":${{ github.event.pull_request.number }}' + fi + curl -fL \ + -X POST \ -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ github.token }}" \ -H "X-GitHub-Api-Version: 2022-11-28" \ - /repos/${{ github.repository }}/statuses/${{ github.event.pull_request.head.sha || github.sha }} \ - -f state='pending' \ - -f context='Ibex Private CI' \ - -f description='Queued' - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Trigger Private CI - run: | - gh workflow run ibex-private-ci.yml --repo lowRISC/lowrisc-private-ci \ - -f ref="${{ github.event.pull_request.head.sha || github.sha }}" \ - -f sha="${{ steps.merge.outputs.merge_sha || github.sha }}" - env: - GITHUB_TOKEN: ${{ secrets.LOWRISC_PRIVATE_CI_PAT }} + https://api.github.com/repos/${{ github.repository }}/dispatches \ + -d '{"event_type":"cross-repo-ci","client_payload":{'"$PAYLOAD"'}}' diff --git a/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml b/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml index 6f24e9256b..3ef833e54f 100644 --- a/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml +++ b/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml @@ -689,6 +689,21 @@ rtl_params: SecureIbex: 1 +- test: riscv_ram_intg_test + description: > + Randomly corrupt one of the RAM MUBI values in the middle of program execution + iterations: 15 + gen_test: riscv_rand_instr_test + gen_opts: > + +instr_cnt=10000 + +num_of_sub_program=5 + +gen_all_csrs_by_default=1 + +add_csr_write=MSTATUS,MEPC,MCAUSE,MTVAL,0x7c0,0x7c1 + +no_csr_instr=0 + rtl_test: core_ibex_ram_intg_test + rtl_params: + SecureIbex: 1 + - test: riscv_icache_intg_test description: > Randomly corrupt the instruction cache once in the middle of program execution diff --git a/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv b/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv index 40a17f30ea..14f77c1bcf 100644 --- a/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv +++ b/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv @@ -199,6 +199,123 @@ class core_ibex_rf_intg_test extends core_ibex_base_test; endclass +class core_ibex_ram_intg_test extends core_ibex_base_test; + `uvm_component_utils(core_ibex_ram_intg_test) + `uvm_component_new + + uvm_report_server rs; + + virtual task send_stimulus(); + int rnd_delay; + int unsigned bit_idx; + logic [31:0] orig_val, glitch_val; + logic alert_major_internal; + string glitch_path, alert_major_internal_path; + string glitch_paths[]; + string signals[]; + string scr_signals[]; + int unsigned scr_signals_idx; + string adv_signals[]; + int unsigned adv_signals_idx; + string ram_path; + int unsigned bank_idx, ram_idx, glitch_idx; + string top_path = "core_ibex_tb_top.dut.u_ibex_top"; + string bank_paths[]; + + // Hard coded paths for the data and tag bank. + bank_paths = { + "gen_rams.gen_rams_inner[0].gen_scramble_rams.tag_bank", + "gen_rams.gen_rams_inner[1].gen_scramble_rams.tag_bank", + "gen_rams.gen_rams_inner[0].gen_scramble_rams.data_bank", + "gen_rams.gen_rams_inner[1].gen_scramble_rams.data_bank" + }; + + // All banks contain a single prim_ram_1p_adv instance. + ram_path = "u_prim_ram_1p_adv"; + + scr_signals = { + "write_en_d", + "write_en_q", + "addr_collision_d", + "addr_collision_q", + "write_scr_pending_d", + "write_pending_q", + "rvalid_q", + "read_en_buf" + }; + + adv_signals = { + "req_q", + "req_d", + "write_q", + "write_d", + "rvalid_q", + "rvalid_d", + "rvalid_sram_q", + "rvalid_sram_d" + }; + + `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(scr_signals_idx, scr_signals_idx < scr_signals.size();) + `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(adv_signals_idx, adv_signals_idx < adv_signals.size();) + `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(bank_idx, bank_idx < bank_paths.size();) + `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(rnd_delay, rnd_delay > 1000; rnd_delay < 10_000;) + + signals = { + scr_signals[scr_signals_idx], + adv_signals[adv_signals_idx] + }; + + // Assemble paths and do the final muxing of the target glitch path below. + glitch_paths = { + $sformatf("%s.%s.%s", top_path, bank_paths[bank_idx], signals[0]), + $sformatf("%s.%s.%s.%s", top_path, bank_paths[bank_idx], ram_path, signals[1]) + }; + + `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(glitch_idx, glitch_idx < glitch_paths.size();) + + glitch_path = glitch_paths[glitch_idx]; + + vseq.start(env.vseqr); + clk_vif.wait_n_clks(rnd_delay); + + `uvm_info(`gfn, $sformatf("Reading value of %s", glitch_path), UVM_LOW) + `DV_CHECK_FATAL(uvm_hdl_read(glitch_path, orig_val)); + `uvm_info(`gfn, $sformatf("Read %x", orig_val), UVM_LOW) + + `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(bit_idx, bit_idx < 4;) + + glitch_val = orig_val; + glitch_val ^= 1 << bit_idx; + + // Disable TB assertion for alerts. + `DV_ASSERT_CTRL_REQ("tb_no_alerts_triggered", 1'b0) + + `uvm_info(`gfn, $sformatf("Forcing %s to value 'h%0x", glitch_path, glitch_val), UVM_LOW) + `DV_CHECK_FATAL(uvm_hdl_force(glitch_path, glitch_val)); + + // Leave glitch applied for one clock cycle. + clk_vif.wait_n_clks(1); + + // Check that the alert matches our expectation. + alert_major_internal_path = $sformatf("%s.alert_major_internal_o", top_path); + `DV_CHECK_FATAL(uvm_hdl_read(alert_major_internal_path, alert_major_internal)) + `DV_CHECK_FATAL(alert_major_internal, "Major alert did not fire!") + + // Release glitch. + `DV_CHECK_FATAL(uvm_hdl_release(glitch_path)) + `uvm_info(`gfn, $sformatf("Releasing force of %s", glitch_path), UVM_LOW) + + // Re-enable TB assertion for alerts. + `DV_ASSERT_CTRL_REQ("tb_no_alerts_triggered", 1'b1) + + // Complete the test at this point because cosimulation does not model faults so will cause + // a mis-match and a test failure. + rs = uvm_report_server::get_server(); + rs.report_summarize(); + $finish(); + endtask +endclass + // Test that corrupts the instruction cache and checks that an appropriate alert occurs. class core_ibex_icache_intg_test extends core_ibex_base_test;