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:
@@ -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')
|
||||
}};
|
||||
|
||||
Reference in New Issue
Block a user