13931Ssaidi@eecs.umich.edu// Copyright (c) 2006-2007 The Regents of The University of Michigan
23388Sgblack@eecs.umich.edu// All rights reserved.
33388Sgblack@eecs.umich.edu//
43388Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
53388Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are
63388Sgblack@eecs.umich.edu// met: redistributions of source code must retain the above copyright
73388Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
83388Sgblack@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
93388Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
103388Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution;
113388Sgblack@eecs.umich.edu// neither the name of the copyright holders nor the names of its
123388Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from
133388Sgblack@eecs.umich.edu// this software without specific prior written permission.
143388Sgblack@eecs.umich.edu//
153388Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
163388Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
173388Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
183388Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
193388Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
203388Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
213388Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
223388Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
233388Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
243388Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
253388Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
263388Sgblack@eecs.umich.edu//
273388Sgblack@eecs.umich.edu// Authors: Ali Saidi
283388Sgblack@eecs.umich.edu//          Gabe Black
293388Sgblack@eecs.umich.edu//          Steve Reinhardt
303388Sgblack@eecs.umich.edu
313388Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////
323388Sgblack@eecs.umich.edu//
333388Sgblack@eecs.umich.edu// Mem utility templates and functions
343388Sgblack@eecs.umich.edu//
353388Sgblack@eecs.umich.edu
367741Sgblack@eecs.umich.edu// This template provides the execute functions for a load
373388Sgblack@eecs.umich.edudef template LoadExecute {{
3812234Sgabeblack@google.com        Fault %(class_name)s::execute(ExecContext *xc,
393388Sgblack@eecs.umich.edu                Trace::InstRecord *traceData) const
403388Sgblack@eecs.umich.edu        {
413388Sgblack@eecs.umich.edu            Fault fault = NoFault;
423388Sgblack@eecs.umich.edu            Addr EA;
433931Ssaidi@eecs.umich.edu            %(fp_enable_check)s;
443388Sgblack@eecs.umich.edu            %(op_decl)s;
453388Sgblack@eecs.umich.edu            %(op_rd)s;
463388Sgblack@eecs.umich.edu            %(ea_code)s;
473766Sgblack@eecs.umich.edu            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
483391Sgblack@eecs.umich.edu            %(fault_check)s;
497741Sgblack@eecs.umich.edu            if (fault == NoFault) {
504648Sgblack@eecs.umich.edu                %(EA_trunc)s
518442Sgblack@eecs.umich.edu                fault = readMemAtomic(xc, traceData, EA, Mem, %(asi_val)s);
523391Sgblack@eecs.umich.edu            }
537741Sgblack@eecs.umich.edu            if (fault == NoFault) {
543391Sgblack@eecs.umich.edu                %(code)s;
553391Sgblack@eecs.umich.edu            }
567741Sgblack@eecs.umich.edu            if (fault == NoFault) {
577741Sgblack@eecs.umich.edu                // Write the resulting state to the execution context
587741Sgblack@eecs.umich.edu                %(op_wb)s;
593388Sgblack@eecs.umich.edu            }
603388Sgblack@eecs.umich.edu
613388Sgblack@eecs.umich.edu            return fault;
623388Sgblack@eecs.umich.edu        }
633792Sgblack@eecs.umich.edu}};
643388Sgblack@eecs.umich.edu
653792Sgblack@eecs.umich.edudef template LoadInitiateAcc {{
6612234Sgabeblack@google.com        Fault %(class_name)s::initiateAcc(ExecContext * xc,
673388Sgblack@eecs.umich.edu                Trace::InstRecord * traceData) const
683388Sgblack@eecs.umich.edu        {
693388Sgblack@eecs.umich.edu            Fault fault = NoFault;
703388Sgblack@eecs.umich.edu            Addr EA;
713931Ssaidi@eecs.umich.edu            %(fp_enable_check)s;
723792Sgblack@eecs.umich.edu            %(op_decl)s;
733792Sgblack@eecs.umich.edu            %(op_rd)s;
743388Sgblack@eecs.umich.edu            %(ea_code)s;
753766Sgblack@eecs.umich.edu            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
763391Sgblack@eecs.umich.edu            %(fault_check)s;
777741Sgblack@eecs.umich.edu            if (fault == NoFault) {
784648Sgblack@eecs.umich.edu                %(EA_trunc)s
7911303Ssteve.reinhardt@amd.com                fault = initiateMemRead(xc, traceData, EA, Mem, %(asi_val)s);
803391Sgblack@eecs.umich.edu            }
813388Sgblack@eecs.umich.edu            return fault;
823388Sgblack@eecs.umich.edu        }
833792Sgblack@eecs.umich.edu}};
843388Sgblack@eecs.umich.edu
853792Sgblack@eecs.umich.edudef template LoadCompleteAcc {{
8612234Sgabeblack@google.com        Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext * xc,
873388Sgblack@eecs.umich.edu                Trace::InstRecord * traceData) const
883388Sgblack@eecs.umich.edu        {
893388Sgblack@eecs.umich.edu            Fault fault = NoFault;
903792Sgblack@eecs.umich.edu            %(op_decl)s;
913792Sgblack@eecs.umich.edu            %(op_rd)s;
928442Sgblack@eecs.umich.edu            getMem(pkt, Mem, traceData);
933388Sgblack@eecs.umich.edu            %(code)s;
947741Sgblack@eecs.umich.edu            if (fault == NoFault) {
953792Sgblack@eecs.umich.edu                %(op_wb)s;
963388Sgblack@eecs.umich.edu            }
973388Sgblack@eecs.umich.edu            return fault;
983388Sgblack@eecs.umich.edu        }
993388Sgblack@eecs.umich.edu}};
1003388Sgblack@eecs.umich.edu
1017741Sgblack@eecs.umich.edu// This template provides the execute functions for a store
1023388Sgblack@eecs.umich.edudef template StoreExecute {{
10312234Sgabeblack@google.com        Fault %(class_name)s::execute(ExecContext *xc,
1043388Sgblack@eecs.umich.edu                Trace::InstRecord *traceData) const
1053388Sgblack@eecs.umich.edu        {
1063388Sgblack@eecs.umich.edu            Fault fault = NoFault;
1077741Sgblack@eecs.umich.edu            // This is to support the conditional store in cas instructions.
1087741Sgblack@eecs.umich.edu            // It should be optomized out in all the others
1093439Sgblack@eecs.umich.edu            bool storeCond = true;
1103388Sgblack@eecs.umich.edu            Addr EA;
1113931Ssaidi@eecs.umich.edu            %(fp_enable_check)s;
1123388Sgblack@eecs.umich.edu            %(op_decl)s;
1133388Sgblack@eecs.umich.edu            %(op_rd)s;
1143388Sgblack@eecs.umich.edu            %(ea_code)s;
1153766Sgblack@eecs.umich.edu            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
1163391Sgblack@eecs.umich.edu            %(fault_check)s;
1177741Sgblack@eecs.umich.edu            if (fault == NoFault) {
1183391Sgblack@eecs.umich.edu                %(code)s;
1193391Sgblack@eecs.umich.edu            }
1207741Sgblack@eecs.umich.edu            if (storeCond && fault == NoFault) {
1214648Sgblack@eecs.umich.edu                %(EA_trunc)s
1228442Sgblack@eecs.umich.edu                fault = writeMemAtomic(xc, traceData, Mem, EA, %(asi_val)s, 0);
1233388Sgblack@eecs.umich.edu            }
1247741Sgblack@eecs.umich.edu            if (fault == NoFault) {
1257741Sgblack@eecs.umich.edu                // Write the resulting state to the execution context
1267741Sgblack@eecs.umich.edu                %(op_wb)s;
1273388Sgblack@eecs.umich.edu            }
1283388Sgblack@eecs.umich.edu
1293388Sgblack@eecs.umich.edu            return fault;
1303388Sgblack@eecs.umich.edu        }
1313792Sgblack@eecs.umich.edu}};
1323388Sgblack@eecs.umich.edu
1333792Sgblack@eecs.umich.edudef template StoreInitiateAcc {{
13412234Sgabeblack@google.com        Fault %(class_name)s::initiateAcc(ExecContext * xc,
1353388Sgblack@eecs.umich.edu                Trace::InstRecord * traceData) const
1363388Sgblack@eecs.umich.edu        {
1373388Sgblack@eecs.umich.edu            Fault fault = NoFault;
1383439Sgblack@eecs.umich.edu            bool storeCond = true;
1393388Sgblack@eecs.umich.edu            Addr EA;
1403931Ssaidi@eecs.umich.edu            %(fp_enable_check)s;
1413388Sgblack@eecs.umich.edu            %(op_decl)s;
1424040Ssaidi@eecs.umich.edu
1433388Sgblack@eecs.umich.edu            %(op_rd)s;
1443388Sgblack@eecs.umich.edu            %(ea_code)s;
1453766Sgblack@eecs.umich.edu            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
1463391Sgblack@eecs.umich.edu            %(fault_check)s;
1477741Sgblack@eecs.umich.edu            if (fault == NoFault) {
1483391Sgblack@eecs.umich.edu                %(code)s;
1493391Sgblack@eecs.umich.edu            }
1507741Sgblack@eecs.umich.edu            if (storeCond && fault == NoFault) {
1514648Sgblack@eecs.umich.edu                %(EA_trunc)s
1528442Sgblack@eecs.umich.edu                fault = writeMemTiming(xc, traceData, Mem, EA, %(asi_val)s, 0);
1533388Sgblack@eecs.umich.edu            }
1543388Sgblack@eecs.umich.edu            return fault;
1553388Sgblack@eecs.umich.edu        }
1563792Sgblack@eecs.umich.edu}};
1573388Sgblack@eecs.umich.edu
1583792Sgblack@eecs.umich.edudef template StoreCompleteAcc {{
15912234Sgabeblack@google.com        Fault %(class_name)s::completeAcc(PacketPtr, ExecContext * xc,
1603388Sgblack@eecs.umich.edu                Trace::InstRecord * traceData) const
1613388Sgblack@eecs.umich.edu        {
1623388Sgblack@eecs.umich.edu            return NoFault;
1633388Sgblack@eecs.umich.edu        }
1643388Sgblack@eecs.umich.edu}};
1653388Sgblack@eecs.umich.edu
1667741Sgblack@eecs.umich.edu// Here are some code snippets which check for various fault conditions
1673391Sgblack@eecs.umich.edulet {{
1683792Sgblack@eecs.umich.edu    LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc]
1693792Sgblack@eecs.umich.edu    StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc]
1704040Ssaidi@eecs.umich.edu
1713391Sgblack@eecs.umich.edu    # The LSB can be zero, since it's really the MSB in doubles and quads
1723391Sgblack@eecs.umich.edu    # and we're dealing with doubles
1733391Sgblack@eecs.umich.edu    BlockAlignmentFaultCheck = '''
1747741Sgblack@eecs.umich.edu        if (RD & 0xe)
17510474Sandreas.hansson@arm.com            fault = std::make_shared<IllegalInstruction>();
1767741Sgblack@eecs.umich.edu        else if (EA & 0x3f)
17710474Sandreas.hansson@arm.com            fault = std::make_shared<MemAddressNotAligned>();
1783391Sgblack@eecs.umich.edu    '''
1793835Sgblack@eecs.umich.edu    TwinAlignmentFaultCheck = '''
1807741Sgblack@eecs.umich.edu        if (RD & 0x1)
18110474Sandreas.hansson@arm.com            fault = std::make_shared<IllegalInstruction>();
1827741Sgblack@eecs.umich.edu        else if (EA & 0xf)
18310474Sandreas.hansson@arm.com            fault = std::make_shared<MemAddressNotAligned>();
1843835Sgblack@eecs.umich.edu    '''
1853391Sgblack@eecs.umich.edu    # XXX Need to take care of pstate.hpriv as well. The lower ASIs
1863391Sgblack@eecs.umich.edu    # are split into ones that are available in priv and hpriv, and
1873391Sgblack@eecs.umich.edu    # those that are only available in hpriv
1883391Sgblack@eecs.umich.edu    AlternateASIPrivFaultCheck = '''
1898829Sgblack@eecs.umich.edu        if ((!Pstate.priv && !Hpstate.hpriv &&
1907741Sgblack@eecs.umich.edu             !asiIsUnPriv((ASI)EXT_ASI)) ||
1918829Sgblack@eecs.umich.edu            (!Hpstate.hpriv && asiIsHPriv((ASI)EXT_ASI)))
19210474Sandreas.hansson@arm.com            fault = std::make_shared<PrivilegedAction>();
1938829Sgblack@eecs.umich.edu        else if (asiIsAsIfUser((ASI)EXT_ASI) && !Pstate.priv)
19410474Sandreas.hansson@arm.com            fault = std::make_shared<PrivilegedAction>();
1953391Sgblack@eecs.umich.edu    '''
1963391Sgblack@eecs.umich.edu
1974648Sgblack@eecs.umich.edu    TruncateEA = '''
19811981Snikos.nikoleris@arm.com        if (!FullSystem) {
1998829Sgblack@eecs.umich.edu            EA = Pstate.am ? EA<31:0> : EA;
20011981Snikos.nikoleris@arm.com        }
2014648Sgblack@eecs.umich.edu    '''
2023391Sgblack@eecs.umich.edu}};
2033391Sgblack@eecs.umich.edu
2047741Sgblack@eecs.umich.edu// A simple function to generate the name of the macro op of a certain
2057741Sgblack@eecs.umich.edu// instruction at a certain micropc
2063391Sgblack@eecs.umich.edulet {{
2073391Sgblack@eecs.umich.edu    def makeMicroName(name, microPc):
2083616Sgblack@eecs.umich.edu            return name + "::" + name + "_" + str(microPc)
2093391Sgblack@eecs.umich.edu}};
2103391Sgblack@eecs.umich.edu
2117741Sgblack@eecs.umich.edu// This function properly generates the execute functions for one of the
2127741Sgblack@eecs.umich.edu// templates above. This is needed because in one case, ea computation,
2137741Sgblack@eecs.umich.edu// fault checks and the actual code all occur in the same function,
2147741Sgblack@eecs.umich.edu// and in the other they're distributed across two. Also note that for
2157741Sgblack@eecs.umich.edu// execute functions, the name of the base class doesn't matter.
2163388Sgblack@eecs.umich.edulet {{
2173949Sgblack@eecs.umich.edu    def doSplitExecute(execute, name, Name, asi, opt_flags, microParam):
2183810Sgblack@eecs.umich.edu        microParam["asi_val"] = asi;
2193792Sgblack@eecs.umich.edu        iop = InstObjParams(name, Name, '', microParam, opt_flags)
2203792Sgblack@eecs.umich.edu        (execf, initf, compf) = execute
2213792Sgblack@eecs.umich.edu        return execf.subst(iop) + initf.subst(iop) + compf.subst(iop)
2223439Sgblack@eecs.umich.edu
2233439Sgblack@eecs.umich.edu
2244040Ssaidi@eecs.umich.edu    def doDualSplitExecute(code, postacc_code, eaRegCode, eaImmCode, execute,
2253810Sgblack@eecs.umich.edu            faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags):
2263388Sgblack@eecs.umich.edu        executeCode = ''
2273388Sgblack@eecs.umich.edu        for (eaCode, name, Name) in (
2283388Sgblack@eecs.umich.edu                (eaRegCode, nameReg, NameReg),
2293388Sgblack@eecs.umich.edu                (eaImmCode, nameImm, NameImm)):
2304040Ssaidi@eecs.umich.edu            microParams = {"code": code, "postacc_code" : postacc_code,
2314648Sgblack@eecs.umich.edu                "ea_code": eaCode, "fault_check": faultCode,
2324648Sgblack@eecs.umich.edu                "EA_trunc" : TruncateEA}
2333792Sgblack@eecs.umich.edu            executeCode += doSplitExecute(execute, name, Name,
2343810Sgblack@eecs.umich.edu                    asi, opt_flags, microParams)
2353388Sgblack@eecs.umich.edu        return executeCode
2363388Sgblack@eecs.umich.edu}};
237