diff --git a/src/cpu/testers/traffic_gen/base.cc b/src/cpu/testers/traffic_gen/base.cc index 03cf2a939b..be02e6e377 100644 --- a/src/cpu/testers/traffic_gen/base.cc +++ b/src/cpu/testers/traffic_gen/base.cc @@ -527,19 +527,20 @@ BaseTrafficGen::createNvm(Tick duration, } std::shared_ptr -BaseTrafficGen::createStrided(Tick duration, - Addr start_addr, Addr end_addr, Addr blocksize, - Addr stride_size, int gen_id, - Tick min_period, Tick max_period, - uint8_t read_percent, Addr data_limit) +BaseTrafficGen::createStrided( + Tick duration, + Addr start_addr, Addr end_addr, Addr offset, + Addr block_size, Addr superblock_size, Addr stride_size, + Tick min_period, Tick max_period, + uint8_t read_percent, Addr data_limit) { - return std::shared_ptr(new StridedGen(*this, requestorId, - duration, start_addr, - end_addr, blocksize, - system->cacheLineSize(), - stride_size, gen_id, - min_period, max_period, - read_percent, data_limit)); + return std::shared_ptr(new StridedGen( + *this, requestorId, duration, + system->cacheLineSize(), + start_addr, end_addr, offset, + block_size, superblock_size, stride_size, + min_period, max_period, + read_percent, data_limit)); } std::shared_ptr diff --git a/src/cpu/testers/traffic_gen/base.hh b/src/cpu/testers/traffic_gen/base.hh index 530da6d718..274e33570c 100644 --- a/src/cpu/testers/traffic_gen/base.hh +++ b/src/cpu/testers/traffic_gen/base.hh @@ -320,8 +320,8 @@ class BaseTrafficGen : public ClockedObject std::shared_ptr createStrided( Tick duration, - Addr start_addr, Addr end_addr, Addr blocksize, - Addr stride_size, int gen_id, + Addr start_addr, Addr end_addr, Addr offset, + Addr block_size, Addr superblock_size, Addr stride_size, Tick min_period, Tick max_period, uint8_t read_percent, Addr data_limit); diff --git a/src/cpu/testers/traffic_gen/strided_gen.cc b/src/cpu/testers/traffic_gen/strided_gen.cc index 7823b93ebe..073bac4f1a 100644 --- a/src/cpu/testers/traffic_gen/strided_gen.cc +++ b/src/cpu/testers/traffic_gen/strided_gen.cc @@ -46,11 +46,28 @@ namespace gem5 { +StridedGen::StridedGen(SimObject& obj, RequestorID requestor_id, + Tick duration, Addr cacheline_size, + Addr start_addr, Addr end_addr, Addr offset, + Addr block_size, Addr superblock_size, Addr stride_size, + Tick min_period, Tick max_period, + uint8_t read_percent, Addr data_limit) + : StochasticGen(obj, requestor_id, duration, start_addr, end_addr, + block_size, cacheline_size, min_period, max_period, + read_percent, data_limit), + offset(offset), superblockSize(superblock_size), strideSize(stride_size), + nextAddr(0), dataManipulated(0) +{ + assert(superblock_size % block_size == 0); + assert(offset % superblock_size == 0); + assert(stride_size % superblock_size == 0); +} + void StridedGen::enter() { // reset the address and the data counter - nextAddr = startAddr + genID * blocksize; + nextAddr = startAddr + offset; dataManipulated = 0; } @@ -74,14 +91,20 @@ StridedGen::getNextPacket() isRead ? MemCmd::ReadReq : MemCmd::WriteReq); // increment the address - nextAddr += strideSize; + nextAddr += blocksize; + + // if we have completed reading a block we need to jump + // (strideSize - blockSize) bytes to start reading the next block + if ((nextAddr - (startAddr + offset)) % superblockSize == 0) { + nextAddr += (strideSize - superblockSize); + } // If we have reached the end of the address space, reset the // address to the start of the range if (nextAddr > endAddr) { DPRINTF(TrafficGen, "Wrapping address to the start of " "the range\n"); - nextAddr = startAddr + genID * blocksize; + nextAddr = startAddr + offset; } return pkt; diff --git a/src/cpu/testers/traffic_gen/strided_gen.hh b/src/cpu/testers/traffic_gen/strided_gen.hh index 4e3ad80cec..7770f70c45 100644 --- a/src/cpu/testers/traffic_gen/strided_gen.hh +++ b/src/cpu/testers/traffic_gen/strided_gen.hh @@ -71,35 +71,26 @@ class StridedGen : public StochasticGen * * @param obj SimObject owning this sequence generator * @param requestor_id RequestorID related to the memory requests - * @param _duration duration of this state before transitioning + * @param cacheline_size cache line size in the system + * @param duration duration of this state before transitioning * @param start_addr Start address * @param end_addr End address - * @param _blocksize Size used for transactions injected - * @param cacheline_size cache line size in the system + * @param offset The offset to start_addr for generating addresses. + * First generated address = start_addr + offset. + * @param block_size Size used for transactions injected * @param stride_size The strided size for consecutive requests - * @param gen_id The order of traffic generator in a list of strided \ - * traffic generators, this param is used to offset the start address of \ - * each generator accordingly with others. + * @param superblock_size Number of bytes to read before taking a stride * @param min_period Lower limit of random inter-transaction time * @param max_period Upper limit of random inter-transaction time * @param read_percent Percent of transactions that are reads * @param data_limit Upper limit on how much data to read/write */ - StridedGen(SimObject &obj, - RequestorID requestor_id, Tick _duration, - Addr start_addr, Addr end_addr, - Addr _blocksize, Addr cacheline_size, - Addr stride_size, int gen_id, - Tick min_period, Tick max_period, - uint8_t read_percent, Addr data_limit) - : StochasticGen(obj, requestor_id, _duration, start_addr, end_addr, - _blocksize, cacheline_size, min_period, max_period, - read_percent, data_limit), - nextAddr(0), - dataManipulated(0), - strideSize(stride_size), - genID(gen_id) - { } + StridedGen(SimObject& obj, RequestorID requestor_id, + Tick duration, Addr cacheline_size, + Addr start_addr, Addr end_addr, Addr offset, + Addr block_size, Addr superblock_size, Addr stride_size, + Tick min_period, Tick max_period, + uint8_t read_percent, Addr data_limit); void enter(); @@ -108,6 +99,12 @@ class StridedGen : public StochasticGen Tick nextPacketTick(bool elastic, Tick delay) const; private: + + Addr offset; + Addr superblockSize; + /* The size of the access stride */ + Addr strideSize; + /** Address of next request */ Addr nextAddr; @@ -117,17 +114,6 @@ class StridedGen : public StochasticGen * generating requests. */ Addr dataManipulated; - - /* The size by which consequent requests are separated */ - Addr strideSize; - - /** - * This param is used to indicate the order of a traffic - * generator among a set of traffic generators, then it - * is used to calculate the start address separately for - * each traffic generator in a list of generators. - */ - int genID; }; } // namespace gem5 diff --git a/src/cpu/testers/traffic_gen/traffic_gen.cc b/src/cpu/testers/traffic_gen/traffic_gen.cc index 6eab4600ac..51afd3c9fd 100644 --- a/src/cpu/testers/traffic_gen/traffic_gen.cc +++ b/src/cpu/testers/traffic_gen/traffic_gen.cc @@ -287,6 +287,35 @@ TrafficGen::parseConfig() DPRINTF(TrafficGen, "State: %d NvmGen\n", id); } } + } else if (mode == "STRIDED") { + uint32_t read_percent; + Addr start_addr; + Addr end_addr; + Addr offset; + Addr blocksize; + Addr superblock_size; + Addr stride_size; + Tick min_period; + Tick max_period; + Addr data_limit; + + is >> read_percent >> start_addr >> end_addr >> offset >> + blocksize >> superblock_size >> stride_size >> + min_period >> max_period >> data_limit; + + DPRINTF(TrafficGen, "%s, addr %x to %x with offset %x, " + "size %d, super size %d, stride size %d, " + "period %d to %d, %d%% reads\n", + mode, start_addr, end_addr, offset, blocksize, + superblock_size, stride_size, min_period, + max_period, read_percent); + + states[id] = createStrided( + duration, start_addr, end_addr, offset, + blocksize, superblock_size, stride_size, + min_period, max_period, read_percent, data_limit); + + DPRINTF(TrafficGen, "State: %d StridedGen\n", id); } else { fatal("%s: Unknown traffic generator mode: %s", name(), mode); diff --git a/src/python/SConscript b/src/python/SConscript index eaaea203f0..ec3b03cdcf 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -241,6 +241,10 @@ PySource('gem5.components.processors', 'gem5/components/processors/linear_generator_core.py') PySource('gem5.components.processors', 'gem5/components/processors/linear_generator.py') +PySource('gem5.components.processors', + 'gem5/components/processors/strided_generator_core.py') +PySource('gem5.components.processors', + 'gem5/components/processors/strided_generator.py') PySource('gem5.components.processors', 'gem5/components/processors/random_generator_core.py') PySource('gem5.components.processors', diff --git a/src/python/gem5/components/processors/strided_generator.py b/src/python/gem5/components/processors/strided_generator.py new file mode 100644 index 0000000000..e14d4f5e0d --- /dev/null +++ b/src/python/gem5/components/processors/strided_generator.py @@ -0,0 +1,101 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from typing import ( + List, + Optional, +) + +from gem5.components.processors.abstract_generator import AbstractGenerator +from gem5.utils.override import overrides + +from .strided_generator_core import StridedGeneratorCore + + +class StridedGenerator(AbstractGenerator): + def __init__( + self, + num_cores: int = 1, + duration: str = "1ms", + rate: str = "100GB/s", + block_size: int = 64, + superblock_size: int = 64, + stride_size: Optional[int] = None, + min_addr: int = 0, + max_addr: int = 32768, + rd_perc: int = 100, + data_limit: int = 0, + ) -> None: + if stride_size is None: + stride_size = num_cores * superblock_size + super().__init__( + cores=self._create_cores( + num_cores=num_cores, + duration=duration, + rate=rate, + block_size=block_size, + superblock_size=superblock_size, + stride_size=stride_size, + min_addr=min_addr, + max_addr=max_addr, + rd_perc=rd_perc, + data_limit=data_limit, + ) + ) + + def _create_cores( + self, + num_cores: int, + duration: str, + rate: str, + block_size: int, + superblock_size: int, + stride_size: int, + min_addr: int, + max_addr: int, + rd_perc: int, + data_limit: int, + ) -> List[StridedGeneratorCore]: + return [ + StridedGeneratorCore( + duration=duration, + rate=rate, + block_size=block_size, + superblock_size=superblock_size, + stride_size=stride_size, + min_addr=min_addr, + max_addr=max_addr, + offset=i * superblock_size, + rd_perc=rd_perc, + data_limit=data_limit, + ) + for i in range(num_cores) + ] + + @overrides(AbstractGenerator) + def start_traffic(self) -> None: + for core in self.cores: + core.start_traffic() diff --git a/src/python/gem5/components/processors/strided_generator_core.py b/src/python/gem5/components/processors/strided_generator_core.py new file mode 100644 index 0000000000..debc945957 --- /dev/null +++ b/src/python/gem5/components/processors/strided_generator_core.py @@ -0,0 +1,106 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from typing import Iterator + +from m5.objects import ( + BaseTrafficGen, + Port, + PyTrafficGen, +) +from m5.ticks import fromSeconds +from m5.util.convert import ( + toLatency, + toMemoryBandwidth, +) + +from gem5.components.processors.abstract_core import AbstractCore +from gem5.components.processors.abstract_generator_core import ( + AbstractGeneratorCore, +) +from gem5.utils.override import overrides + + +class StridedGeneratorCore(AbstractGeneratorCore): + def __init__( + self, + duration: str, + rate: str, + block_size: int, + superblock_size: int, + stride_size: int, + min_addr: int, + max_addr: int, + offset: int, + rd_perc: int, + data_limit: int, + ) -> None: + super().__init__() + + self.generator = PyTrafficGen() + self._duration = duration + self._rate = rate + self._block_size = block_size + self._superblock_size = superblock_size + self._stride_size = stride_size + self._min_addr = min_addr + self._max_addr = max_addr + self._offset = offset + self._rd_perc = rd_perc + self._data_limit = data_limit + + @overrides(AbstractCore) + def connect_dcache(self, port: Port) -> None: + self.generator.port = port + + def _set_traffic(self) -> None: + self._traffic = self._create_traffic() + + def _create_traffic(self) -> Iterator[BaseTrafficGen]: + duration = fromSeconds(toLatency(self._duration)) + rate = toMemoryBandwidth(self._rate) + period = fromSeconds(self._block_size / rate) + min_period = period + max_period = period + yield self.generator.createStrided( + duration, + self._min_addr, + self._max_addr, + self._offset, + self._block_size, + self._superblock_size, + self._stride_size, + min_period, + max_period, + self._rd_perc, + self._data_limit, + ) + yield self.generator.createExit(0) + + @overrides(AbstractGeneratorCore) + def start_traffic(self) -> None: + self._set_traffic() + self.generator.start(self._traffic)