· Bits, Bytes, and Gates
/****************************************************************************
 * memtest_buffer.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;
}

buffer mem_b {
    rand bit[64] in [0..0xFFFFFF] offset;
    rand bit[32] in [1..256]      words;
}

component memtest_c {
    addr_handle_t       base_addr;

    // Binding the mem_b pool to all actions enables
    // all actions to communicate via mem_b objects
    pool mem_b mem_b_p;
    bind mem_b_p *;

    action Write {
        output mem_b                  dat_o;
        rand executor_claim_s<core_s> core;

        exec body {
            repeat (i : dat_o.words) {
                write32(
                    make_handle_from_handle(
                        comp.base_addr, 4*(dat_o.offset+i)),
                    i+1);
            }
        }
    }

    action Copy {
        input mem_b                     dat_i;
        output mem_b                    dat_o;
        rand executor_claim_s<core_s>   core;

        // Ensure we copy the same number of words
        constraint dat_i.words == dat_o.words;

        // Ensure that src/dst regions d not overlap
        constraint (dat_i.offset+(5*dat_i.words) < dat_o.offset) ||
            (dat_i.offset > dat_o.offset+(4*dat_i.words));

        exec body {
            bit[32] tmp;
            repeat (i : dat_o.words) {
                tmp = read32(
                    make_handle_from_handle(comp.base_addr,
                        4*(dat_i.offset+i)));
                write32(
                    make_handle_from_handle(comp.base_addr,
                        4*(dat_o.offset+i)),
                    tmp);
            }
        }
    }

    action Check {
        input mem_b                     dat_i;
        rand executor_claim_s<core_s>   core;

        exec body {
            bit[32] tmp;
            repeat (i : dat_i.words) {
                tmp = read32(
                    make_handle_from_handle(comp.base_addr,
                        4*(dat_i.offset+i)));
                if (tmp != i+1) {
                    error("0x%08x: expect %d ; receive %d",
                        4*(dat_i.offset+i), i+1, tmp);
                }
            }
        }
    }

    action WriteCopyCheck {
        Write             write;
        Copy              copy;
        Check             check;

        activity {
            write;
            copy;
            check;
            bind write.dat_o copy.dat_i;
            bind copy.dat_o check.dat_i;
        }
    }

    action Write2xCopyCheck {
        Write             write;
        Copy              copy1, copy2;
        Check             check;

        activity {
            write;
            copy1;
            copy2;
            check;
            bind write.dat_o copy1.dat_i;
            bind copy1.dat_o copy2.dat_i;
            bind copy2.dat_o check.dat_i;
        }
    }
}

component pss_top {
    executor_c<core_s>         core[4];
    executor_group_c<core_s>   cores;
    transparent_addr_space_c<> aspace;
    memtest_c                  memtest;

    pool mem_b mem_b_p;
    bind mem_b_p *;

    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;
            }
        }
    }

    action Copy2x {
        activity {
            do memtest_c::Write2xCopyCheck;
        }
    }
}
Copyright 2014-2024 Matthew Ballance. All Rights Reserved
The views and opinions expressed above are solely those of the author and do not represent those of my employer or any other party.