From 035bf6136c334d85bff648e147c67fe176fa6953 Mon Sep 17 00:00:00 2001 From: Cesar Fuguet Date: Tue, 8 Oct 2024 22:52:56 +0200 Subject: [PATCH] tb: add single addr sequence --- rtl/tb/hpdcache_tb.cpp | 3 + .../hpdcache_test_single_addr_seq.h | 268 ++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 rtl/tb/sequence_lib/hpdcache_test_single_addr_seq.h diff --git a/rtl/tb/hpdcache_tb.cpp b/rtl/tb/hpdcache_tb.cpp index c590f22..495513c 100644 --- a/rtl/tb/hpdcache_tb.cpp +++ b/rtl/tb/hpdcache_tb.cpp @@ -46,6 +46,7 @@ #include "sequence_lib/hpdcache_test_random_seq.h" #include "sequence_lib/hpdcache_test_read_seq.h" #include "sequence_lib/hpdcache_test_write_seq.h" +#include "sequence_lib/hpdcache_test_single_addr_seq.h" class hpdcache_test { @@ -300,6 +301,8 @@ class hpdcache_test seq = std::make_shared("read"); } else if (seq_name == "write") { seq = std::make_shared("write"); + } else if (seq_name == "single_addr") { + seq = std::make_shared("single_addr"); } else { std::cout << "error: sequence " << seq_name << " not found" << std::endl; exit(EXIT_FAILURE); diff --git a/rtl/tb/sequence_lib/hpdcache_test_single_addr_seq.h b/rtl/tb/sequence_lib/hpdcache_test_single_addr_seq.h new file mode 100644 index 0000000..97fc509 --- /dev/null +++ b/rtl/tb/sequence_lib/hpdcache_test_single_addr_seq.h @@ -0,0 +1,268 @@ +/** + * Copyright 2023,2024 CEA* + * *Commissariat a l'Energie Atomique et aux Energies Alternatives (CEA) + * + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Licensed under the Solderpad Hardware License v 2.1 (the “License”); you + * may not use this file except in compliance with the License, or, at your + * option, the Apache License version 2.0. You may obtain a copy of the + * License at + * + * https://solderpad.org/licenses/SHL-2.1/ + * + * Unless required by applicable law or agreed to in writing, any work + * 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. + */ +/** + * Author : Cesar Fuguet + * Date : October, 2024 + * Description: Class definition of the HPDCACHE test single address sequence + */ +#ifndef __HPDCACHE_TEST_SINGLE_ADDR_SEQ_H__ +#define __HPDCACHE_TEST_SINGLE_ADDR_SEQ_H__ + +#include +#include "scv.h" +#include "hpdcache_test_defs.h" +#include "hpdcache_test_sequence.h" + +class hpdcache_test_single_addr_seq : public hpdcache_test_sequence +{ +public: + + hpdcache_test_single_addr_seq(sc_core::sc_module_name nm) + : hpdcache_test_sequence(nm, "random_seq") + { + SC_THREAD(run); + sensitive << clk_i.pos(); + + seg[0].set_base (0x00000000ULL); + seg[0].set_length (0x00004000ULL); + seg[0].set_uncached (false); + seg[0].set_amo_supported (true); + seg[0].set_wr_policy_hint (hpdcache_test_memory_segment::WR_POLICY_RANDOM); + + hpdcache_test_sequence::delay_distribution.push(pair(0, 0), 80); + hpdcache_test_sequence::delay_distribution.push(pair(1, 4), 18); + hpdcache_test_sequence::delay_distribution.push(pair(5, 20), 2); + hpdcache_test_sequence::delay->set_mode(delay_distribution); + + hpdcache_test_sequence::amo_sc_do_distribution.push(false, 25); + hpdcache_test_sequence::amo_sc_do_distribution.push(true, 75); + hpdcache_test_sequence::amo_sc_do->set_mode(amo_sc_do_distribution); + + hpdcache_test_sequence::wr_policy_distribution.push(hpdcache_test_transaction_req::HPDCACHE_WR_POLICY_AUTO, 80); + hpdcache_test_sequence::wr_policy_distribution.push(hpdcache_test_transaction_req::HPDCACHE_WR_POLICY_WB, 10); + hpdcache_test_sequence::wr_policy_distribution.push(hpdcache_test_transaction_req::HPDCACHE_WR_POLICY_WT, 10); + hpdcache_test_sequence::wr_policy->set_mode(wr_policy_distribution); + + hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_LOAD, 400); + hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_STORE, 350); + hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_FENCE, 10); + hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_PREFETCH, 10); +// hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_INVAL_NLINE, 15); +// hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_INVAL_ALL, 15); + hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_FLUSH_NLINE, 10); + hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_FLUSH_ALL, 1); + hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_FLUSH_INVAL_NLINE, 10); + hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_FLUSH_INVAL_ALL, 1); + hpdcache_test_sequence::op->set_mode(op_distribution); + + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_LOAD, 400); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_STORE, 350); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_FENCE, 10); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_PREFETCH, 10); +// hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_INVAL_NLINE, 15); +// hpdcache_test_sequence::op_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_INVAL_ALL, 15); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_FLUSH_NLINE, 10); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_FLUSH_ALL, 1); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_FLUSH_INVAL_NLINE, 10); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_CMO_FLUSH_INVAL_ALL, 1); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_LR, 4); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_SC, 4); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_SWAP, 4); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_ADD, 4); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_AND, 4); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_OR, 4); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_XOR, 4); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_MAX, 4); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_MAXU, 4); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_MIN, 4); + hpdcache_test_sequence::op_amo_distribution.push(hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_MINU, 4); + hpdcache_test_sequence::op_amo->set_mode(op_amo_distribution); + } + +private: + hpdcache_test_sequence::hpdcache_test_memory_segment seg[1]; + scv_smart_ptr > data; + scv_smart_ptr > size; + const unsigned int HPDCACHE_REQ_DATA_BYTES = HPDCACHE_REQ_DATA_WIDTH/8; + + SC_HAS_PROCESS(hpdcache_test_single_addr_seq); + + inline sc_bv create_random_data() + { + data->next(); + return data->read(); + } + + inline uint32_t create_random_size(bool is_amo) + { + if (!is_amo) size->keep_only(0, 3); + else size->keep_only(2, 3); + + size->next(); + return size->read().to_uint(); + } + + std::shared_ptr create_random_transaction(uint64_t addr) + { + std::shared_ptr t; + + while (!is_available_id()) wait(); + + hpdcache_test_memory_segment::wr_policy_e seg_wr_policy = + seg[0].get_wr_policy_hint(); + + bool seg_amo_supported = + seg[0].is_amo_supported(); + bool seg_wr_policy_random = + (seg_wr_policy == hpdcache_test_memory_segment::WR_POLICY_RANDOM); + + t = acquire_transaction(); + + // Select operation + if (seg_amo_supported) { + hpdcache_test_sequence::op_amo->next(); + t->req_op = op_amo->read(); + } else { + hpdcache_test_sequence::op->next(); + t->req_op = op->read(); + } + + t->req_wdata = create_random_data(); + t->req_sid = 0; + t->req_tid = allocate_id(); + t->req_abort = false; + t->req_phys_indexed = false; + + // Select write policy + if (seg_wr_policy_random) { + wr_policy->next(); + t->req_wr_policy_hint = + (hpdcache_test_transaction_req::hpdcache_wr_policy_hint_e)wr_policy->read(); + } else if (seg_wr_policy == hpdcache_test_memory_segment::WR_POLICY_WB) { + t->req_wr_policy_hint = hpdcache_test_transaction_req::HPDCACHE_WR_POLICY_WB; + } else if (seg_wr_policy == hpdcache_test_memory_segment::WR_POLICY_WT) { + t->req_wr_policy_hint = hpdcache_test_transaction_req::HPDCACHE_WR_POLICY_WT; + } else { + t->req_wr_policy_hint = hpdcache_test_transaction_req::HPDCACHE_WR_POLICY_AUTO; + } + + // Select address and size + uint32_t sz = create_random_size( + t->is_amo() || + t->is_amo_sc() || + t->is_amo_lr()); + uint64_t base = seg[0].get_base(); + uint64_t length = seg[0].get_length(); + uint32_t bytes = 1 << sz; + uint64_t address = ((base + (addr % length)) / bytes) * bytes; + + t->req_addr = address; + if (t->is_cmo()) { + t->req_be = 0; + t->req_size = 0; + t->req_uncacheable = false; + t->req_need_rsp = false; + } else { + uint32_t offset = address % HPDCACHE_REQ_DATA_BYTES; + t->req_be = ((1UL << bytes) - 1) << offset; + t->req_size = sz; + t->req_uncacheable = seg[0].is_uncached() ? 1 : 0; + t->req_need_rsp = true; + } + + return t; + } + + std::shared_ptr create_sc_transaction(uint64_t addr, bool uncacheable) + { + std::shared_ptr t; + + while (!is_available_id()) wait(); + + uint32_t sz = create_random_size(true); + uint32_t bytes = 1 << sz; + uint64_t address = (addr / bytes) * bytes; + uint32_t offset = address % HPDCACHE_REQ_DATA_BYTES; + + t = acquire_transaction(); + t->req_op = hpdcache_test_transaction_req::HPDCACHE_REQ_AMO_SC; + t->req_wdata = create_random_data(); + t->req_sid = 0; + t->req_tid = allocate_id(); + t->req_addr = address; + t->req_be = ((1UL << bytes) - 1) << offset; + t->req_size = sz; + t->req_uncacheable = uncacheable; + t->req_need_rsp = true; + + return t; + } + + void run() + { + while (rst_ni == 0) wait(); + + wait(); + + scv_smart_ptr _addr("addr"); + _addr->next(); + uint64_t addr = _addr->read(); + + scv_smart_ptr lrsc_inbetween_instrs; + lrsc_inbetween_instrs->keep_only(0, 10); + lrsc_inbetween_instrs->next(); + + delay->next(); + for (size_t n = 0; n < this->max_transactions; n++) { + std::shared_ptr t; + t = create_random_transaction(addr); + + if (t->is_amo_lr()) { + hpdcache_test_transaction_req prev_lr = *t; + send_transaction(t, delay->read()); + delay->next(); + + amo_sc_do->next(); + if (amo_sc_do->read()) { + for (int i = 0; i < lrsc_inbetween_instrs.read(); i++) { + t = create_random_transaction(addr); + send_transaction(t, delay->read()); + delay->next(); + } + + t = create_sc_transaction(prev_lr.req_addr.to_uint64(), + prev_lr.req_uncacheable); + send_transaction(t, delay->read()); + delay->next(); + lrsc_inbetween_instrs->next(); + } + + continue; + } + send_transaction(t, delay->read()); + delay->next(); + } + + // ask the driver to stop + transaction_fifo_o->write(nullptr); + } +}; + +#endif // __HPDCACHE_TEST_RANDOM_SEQ_H__