/**************************************************************************** * memtest.pss * * Copyright 2023 Matthew Ballance and Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Created on: * Author: ****************************************************************************/ import addr_reg_pkg::*; import executor_pkg::*; struct core_s : executor_trait_s { rand bit[8] id; } component memtest_c { addr_handle_t base_addr; action Write { rand executor_claim_s core; rand bit[64] in [0..0xFFFFFF] offset; rand bit[32] in [1..256] words; exec body { repeat (i : words) { write32( make_handle_from_handle(comp.base_addr, 4*(offset+i)), i+1); } } } action Copy { rand executor_claim_s core; rand bit[64] in [0..0xFFFFFF] src; rand bit[64] in [0..0xFFFFFF] dst; rand bit[32] in [1..256] words; exec body { bit[32] tmp; repeat (i : words) { tmp = read32( make_handle_from_handle(comp.base_addr, 4*(src+i))); write32( make_handle_from_handle(comp.base_addr, 4*(dst+i)), tmp); } } } action Check { rand executor_claim_s core; rand bit[64] in [0..0xFFFFFF] offset; rand bit[32] in [1..256] words; exec body { bit[32] tmp; repeat (i : words) { tmp = read32( make_handle_from_handle(comp.base_addr, 4*(offset+i))); if (tmp != i+1) { error("0x%08x: expect %d ; receive %d", 4*(offset+i), i+1, tmp); } } } } action WriteCopyCheck { Write write; Copy copy; Check check; activity { write; copy; check; } constraint { // Copy reads from same location that Write populated copy.src == write.offset; // Check reads from the same location that Copy populated copy.dst == check.offset; // All actions write the same number of words copy.words == write.words; copy.words == check.words; // Ensure that src/dst regions do not overlap (copy.src+(4*copy.words) < copy.dst) || (copy.src > copy.dst+(4*copy.words)); } } } component pss_top { executor_c core[4]; executor_group_c cores; transparent_addr_space_c<> aspace; memtest_c memtest; exec init { foreach (core[i]) { core[i].trait.id = i; cores.add_executor(core[i]); } // Define a memory region transparent_addr_region_s<> region; region.addr = 0x8000_0000; region.size = 0x1000_0000; memtest.base_addr = aspace.add_region(region); } action Copy_0_1_0 { activity { do memtest_c::WriteCopyCheck with { write.core.trait.id == 0; copy.core.trait.id == 1; check.core.trait.id == 0; } } } action Copy_check_diff_core { activity { do memtest_c::WriteCopyCheck with { write.core.trait.id != check.core.trait.id; } } } action Copy_same_core { activity { do memtest_c::WriteCopyCheck with { write.core.trait.id == copy.core.trait.id; copy.core.trait.id == check.core.trait.id; } } } }