diff options
author | Giacomo Gabrielli <giacomo.gabrielli@arm.com> | 2018-02-26 13:41:08 +0000 |
---|---|---|
committer | Giacomo Gabrielli <giacomo.gabrielli@arm.com> | 2019-05-30 15:55:59 +0000 |
commit | fc61172dbe4e3a93f941227a1f36b7f07e97ab68 (patch) | |
tree | 264b957011c381cdda74d08642c5404ece247b45 /src/cpu/o3 | |
parent | 5365c18f2e309b54d3e37dc98d8cca20ec9d4219 (diff) | |
download | gem5-fc61172dbe4e3a93f941227a1f36b7f07e97ab68.tar.xz |
cpu-o3: Add support for pinned writes
This patch adds support for pinning registers for a certain number of
consecutive writes. This is only relevant for timing CPU models
(functional-only models are unaffected), and it is primarily needed to
provide a realistic execution model for micro-coded operations whose
microops can write to non-overlapping portions of a destination
register, e.g. vector gather loads. In those cases, this mechanism
can disable renaming for a sequence of consecutive writes, thus making
the resulting execution more efficient: allocating a new physical
register for each microop would introduce a read-modify-write chain of
dependencies, while with these modifications the microops can write
back in parallel.
Please note that this new feature is only leveraged by O3CPU for the
time being.
Additional authors:
- Gabor Dozsa <gabor.dozsa@arm.com>
Change-Id: I07eb5fdbd1fa0b748c9bdc1174d9f330fda34f81
Signed-off-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/13520
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'src/cpu/o3')
-rw-r--r-- | src/cpu/o3/free_list.hh | 9 | ||||
-rw-r--r-- | src/cpu/o3/iew_impl.hh | 13 | ||||
-rw-r--r-- | src/cpu/o3/inst_queue_impl.hh | 13 | ||||
-rw-r--r-- | src/cpu/o3/regfile.cc | 6 | ||||
-rw-r--r-- | src/cpu/o3/regfile.hh | 6 | ||||
-rw-r--r-- | src/cpu/o3/rename_impl.hh | 8 | ||||
-rw-r--r-- | src/cpu/o3/rename_map.cc | 25 |
7 files changed, 51 insertions, 29 deletions
diff --git a/src/cpu/o3/free_list.hh b/src/cpu/o3/free_list.hh index 46bebf30d..82ff25d3b 100644 --- a/src/cpu/o3/free_list.hh +++ b/src/cpu/o3/free_list.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 ARM Limited + * Copyright (c) 2016-2018 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -79,10 +79,9 @@ class SimpleFreeList template<class InputIt> void addRegs(InputIt first, InputIt last) { - std::for_each(first, last, - [this](const typename InputIt::value_type& reg) { - this->freeRegs.push(®); - }); + std::for_each(first, last, [this](typename InputIt::value_type& reg) { + this->freeRegs.push(®); + }); } /** Get the next available register from the free list */ diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index 56c182564..5872f90d2 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -1480,11 +1480,14 @@ DefaultIEW<Impl>::writebackInsts() int dependents = instQueue.wakeDependents(inst); for (int i = 0; i < inst->numDestRegs(); i++) { - //mark as Ready - DPRINTF(IEW,"Setting Destination Register %i (%s)\n", - inst->renamedDestRegIdx(i)->index(), - inst->renamedDestRegIdx(i)->className()); - scoreboard->setReg(inst->renamedDestRegIdx(i)); + // Mark register as ready if not pinned + if (inst->renamedDestRegIdx(i)-> + getNumPinnedWritesToComplete() == 0) { + DPRINTF(IEW,"Setting Destination Register %i (%s)\n", + inst->renamedDestRegIdx(i)->index(), + inst->renamedDestRegIdx(i)->className()); + scoreboard->setReg(inst->renamedDestRegIdx(i)); + } } if (dependents) { diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index 20b41e51d..c3e3fdf32 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014, 2017-2018 ARM Limited + * Copyright (c) 2011-2014, 2017-2019 ARM Limited * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * @@ -1033,6 +1033,17 @@ InstructionQueue<Impl>::wakeDependents(const DynInstPtr &completed_inst) continue; } + // Avoid waking up dependents if the register is pinned + dest_reg->decrNumPinnedWritesToComplete(); + if (dest_reg->isPinned()) + completed_inst->setPinnedRegsWritten(); + + if (dest_reg->getNumPinnedWritesToComplete() != 0) { + DPRINTF(IQ, "Reg %d [%s] is pinned, skipping\n", + dest_reg->index(), dest_reg->className()); + continue; + } + DPRINTF(IQ, "Waking any dependents on register %i (%s).\n", dest_reg->index(), dest_reg->className()); diff --git a/src/cpu/o3/regfile.cc b/src/cpu/o3/regfile.cc index cc4bba6b0..afed8f9fa 100644 --- a/src/cpu/o3/regfile.cc +++ b/src/cpu/o3/regfile.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 ARM Limited + * Copyright (c) 2016-2018 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -216,8 +216,8 @@ PhysRegFile::getRegIds(RegClass cls) -> IdRange return std::make_pair(miscRegIds.begin(), miscRegIds.end()); } /* There is no way to make an empty iterator */ - return std::make_pair(PhysIds::const_iterator(), - PhysIds::const_iterator()); + return std::make_pair(PhysIds::iterator(), + PhysIds::iterator()); } PhysRegIdPtr diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index d4b6602ad..352e6ac93 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 ARM Limited + * Copyright (c) 2016-2018 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -70,8 +70,8 @@ class PhysRegFile using VecMode = Enums::VecRegRenameMode; using VecPredRegContainer = TheISA::VecPredRegContainer; public: - using IdRange = std::pair<PhysIds::const_iterator, - PhysIds::const_iterator>; + using IdRange = std::pair<PhysIds::iterator, + PhysIds::iterator>; private: static constexpr auto NumVecElemPerVecReg = TheISA::NumVecElemPerVecReg; diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 43f0b2746..d55bed655 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012, 2014-2016 ARM Limited + * Copyright (c) 2010-2012, 2014-2019 ARM Limited * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * @@ -976,7 +976,9 @@ DefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, ThreadID tid) assert(hb_it != historyBuffer[tid].end()); DPRINTF(Rename, "[tid:%i] Removing history entry with sequence " - "number %i.\n", tid, hb_it->instSeqNum); + "number %i (archReg: %d, newPhysReg: %d, prevPhysReg: %d).\n", + tid, hb_it->instSeqNum, hb_it->archReg.index(), + hb_it->newPhysReg->index(), hb_it->prevPhysReg->index()); // Undo the rename mapping only if it was really a change. // Special regs that are not really renamed (like misc regs @@ -1140,12 +1142,12 @@ DefaultRename<Impl>::renameDestRegs(const DynInstPtr &inst, ThreadID tid) typename RenameMap::RenameInfo rename_result; RegId flat_dest_regid = tc->flattenRegId(dest_reg); + flat_dest_regid.setNumPinnedWrites(dest_reg.getNumPinnedWrites()); rename_result = map->rename(flat_dest_regid); inst->flattenDestReg(dest_idx, flat_dest_regid); - // Mark Scoreboard entry as not ready scoreboard->unsetReg(rename_result.first); DPRINTF(Rename, diff --git a/src/cpu/o3/rename_map.cc b/src/cpu/o3/rename_map.cc index 9d912e582..64f3dbf8c 100644 --- a/src/cpu/o3/rename_map.cc +++ b/src/cpu/o3/rename_map.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017,2019 ARM Limited + * Copyright (c) 2016-2018,2019 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -78,16 +78,23 @@ SimpleRenameMap::rename(const RegId& arch_reg) // requested architected register. PhysRegIdPtr prev_reg = map[arch_reg.flatIndex()]; - // If it's not referencing the zero register, then rename the - // register. - if (arch_reg != zeroReg) { - renamed_reg = freeList->getReg(); - - map[arch_reg.flatIndex()] = renamed_reg; - } else { - // Otherwise return the zero register so nothing bad happens. + if (arch_reg == zeroReg) { assert(prev_reg->isZeroReg()); renamed_reg = prev_reg; + } else if (prev_reg->getNumPinnedWrites() > 0) { + // Do not rename if the register is pinned + assert(arch_reg.getNumPinnedWrites() == 0); // Prevent pinning the + // same register twice + DPRINTF(Rename, "Renaming pinned reg, numPinnedWrites %d\n", + prev_reg->getNumPinnedWrites()); + renamed_reg = prev_reg; + renamed_reg->decrNumPinnedWrites(); + } else { + renamed_reg = freeList->getReg(); + map[arch_reg.flatIndex()] = renamed_reg; + renamed_reg->setNumPinnedWrites(arch_reg.getNumPinnedWrites()); + renamed_reg->setNumPinnedWritesToComplete( + arch_reg.getNumPinnedWrites() + 1); } DPRINTF(Rename, "Renamed reg %d to physical reg %d (%d) old mapping was" |