arch-riscv: Fix implementation of CMO extension instructions

This change introduces a template for store instruction's mem access.
The new template is called CacheBlockBasedStore.

The reasons for not reusing the current Store's mem access template
are as follows,
- The CMO extension instructions operate on cache block size granularity,
while regular load/store instructions operate on data of size 64 bits or
fewer.
- The writeMemAtomicLE/writeMemTimingLE interfaces do not allow passing
nullptr as data. However, CPUs in gem5 rely on (data == NULL) to detect
CACHE_BLOCK_ZERO instructions. Setting `Mem = 0;` to `uint64_t Mem;`
does not solve the problem as the reference is allocated and thus,
it's always true that `&Mem != NULL`. This change uses the
writeMemAtomic/writeMemTiming interfaces instead.
- Per CMO v1.0.1, the instructions in the spec do not generate
address misaligned faults.
- The CMO extension instructions do not use IMM.

Change-Id: I323615639a4ba882fe40a55ed32c7632e0251421
Signed-off-by: Hoa Nguyen <hn@hnpl.org>
This commit is contained in:
Hoa Nguyen
2023-10-30 02:07:04 +00:00
parent d0113185c6
commit 2521ba0664

View File

@@ -228,6 +228,69 @@ def template StoreCompleteAcc {{
}
}};
def template CacheBlockBasedStoreExecute {{
Fault
%(class_name)s::execute(ExecContext *xc,
trace::InstRecord *traceData) const
{
Addr EA;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
Addr cacheBlockSize = xc->tcBase()->getCpuPtr()->cacheLineSize();
uint64_t numOffsetBits = floorLog2(cacheBlockSize);
EA = (EA >> numOffsetBits) << numOffsetBits;
{
Fault fault =
writeMemAtomic(xc, nullptr, EA, cacheBlockSize, memAccessFlags,
nullptr, std::vector<bool>(cacheBlockSize, true));
if (fault != NoFault)
return fault;
}
return NoFault;
}
}};
def template CacheBlockBasedStoreInitiateAcc {{
Fault
%(class_name)s::initiateAcc(ExecContext *xc,
trace::InstRecord *traceData) const
{
Addr EA;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
Addr cacheBlockSize = xc->tcBase()->getCpuPtr()->cacheLineSize();
uint64_t numOffsetBits = floorLog2(cacheBlockSize);
EA = (EA >> numOffsetBits) << numOffsetBits;
{
Fault fault =
writeMemTiming(xc, nullptr, EA, cacheBlockSize, memAccessFlags,
nullptr, std::vector<bool>(cacheBlockSize, true));
if (fault != NoFault)
return fault;
}
return NoFault;
}
}};
def template CacheBlockBasedStoreCompleteAcc {{
Fault
%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
trace::InstRecord *traceData) const
{
return NoFault;
}
}};
def format Load(memacc_code, ea_code = {{EA = rvZext(Rs1 + offset);}},
offset_code={{offset = sext<12>(IMM12);}},
mem_flags=[], inst_flags=[]) {{
@@ -244,9 +307,9 @@ def format Store(memacc_code, ea_code={{EA = rvZext(Rs1 + offset);}},
inst_flags, 'Store', exec_template_base='Store')
}};
def format CBMOp(memacc_code, ea_code={{EA = rvZext(Rs1 + offset);}},
offset_code={{offset = 0;}}, mem_flags=[], inst_flags=[]) {{
def format CBMOp(memacc_code, ea_code={{EA = rvZext(Rs1);}},
offset_code={{;}}, mem_flags=[], inst_flags=[]) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags,
inst_flags, 'Store', exec_template_base='Store')
inst_flags, 'Store', exec_template_base='CacheBlockBasedStore')
}};