blob: 1e416d87ec0333a528723a7dfc5676ebfecf4335 [file] [log] [blame]
// -*- mode:c++ -*-
// Copyright (c) 2015 RISC-V Foundation
// Copyright (c) 2016 The University of Virginia
// 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.
//
// Authors: Alec Roelke
////////////////////////////////////////////////////////////////////
//
// Memory operation instructions
//
def template LoadStoreDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst);
Fault execute(ExecContext *, Trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
Trace::InstRecord *) const override;
};
}};
def template LoadStoreConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst):
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
{
%(constructor)s;
%(offset_code)s;
}
}};
let {{
def LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags,
inst_flags, base_class, postacc_code='', decode_template=BasicDecode,
exec_template_base=''):
# Make sure flags are in lists (convert to lists if not).
mem_flags = makeList(mem_flags)
inst_flags = makeList(inst_flags)
iop = InstObjParams(name, Name, base_class,
{'offset_code': offset_code, 'ea_code': ea_code,
'memacc_code': memacc_code, 'postacc_code': postacc_code },
inst_flags)
if mem_flags:
mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
iop.constructor += s
# select templates
fullExecTemplate = eval(exec_template_base + 'Execute')
initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
# (header_output, decoder_output, decode_block, exec_output)
return (LoadStoreDeclare.subst(iop),
LoadStoreConstructor.subst(iop),
decode_template.subst(iop),
fullExecTemplate.subst(iop) +
initiateAccTemplate.subst(iop) +
completeAccTemplate.subst(iop))
}};
def template LoadExecute {{
Fault
%(class_name)s::execute(
ExecContext *xc, Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
if (fault == NoFault) {
fault = readMemAtomicLE(xc, traceData, EA, Mem, memAccessFlags);
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template LoadInitiateAcc {{
Fault
%(class_name)s::initiateAcc(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_src_decl)s;
%(op_rd)s;
%(ea_code)s;
if (fault == NoFault) {
fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
}
return fault;
}
}};
def template LoadCompleteAcc {{
Fault
%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
getMemLE(pkt, Mem, traceData);
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template StoreExecute {{
Fault
%(class_name)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
fault = writeMemAtomicLE(xc, traceData, Mem, EA, memAccessFlags,
nullptr);
}
if (fault == NoFault) {
%(postacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template StoreInitiateAcc {{
Fault
%(class_name)s::initiateAcc(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
fault = writeMemTimingLE(xc, traceData, Mem, EA,
memAccessFlags, nullptr);
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template StoreCompleteAcc {{
Fault
%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
Trace::InstRecord *traceData) const
{
return NoFault;
}
}};
def format Load(memacc_code, ea_code = {{EA = Rs1 + offset;}},
offset_code={{offset = sext<12>(IMM12);}},
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, 'Load', exec_template_base='Load')
}};
def format Store(memacc_code, ea_code={{EA = Rs1 + offset;}},
offset_code={{offset = sext<12>(IMM5 | (IMM7 << 5));}},
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')
}};