amo.isa revision 11726:11950d45640b
1// -*- mode:c++ -*-
2
3// Copyright (c) 2015 Riscv Developers
4// Copyright (c) 2016 The University of Virginia
5// All rights reserved.
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are
9// met: redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer;
11// redistributions in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution;
14// neither the name of the copyright holders nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Authors: Alec Roelke
31
32////////////////////////////////////////////////////////////////////
33//
34// Atomic memory operation instructions
35//
36output header {{
37    class AtomicMemOp : public RiscvMacroInst
38    {
39    protected:
40        /// Constructor
41        // Each AtomicMemOp has a load and a store phase
42        AtomicMemOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
43                : RiscvMacroInst(mnem, _machInst, __opClass)
44        {}
45
46        std::string generateDisassembly(Addr pc,
47            const SymbolTable *symtab) const;
48    };
49
50    class AtomicMemOpMicro : public RiscvMicroInst
51    {
52    protected:
53        /// Memory request flags.  See mem/request.hh.
54        Request::Flags memAccessFlags;
55
56        /// Constructor
57        AtomicMemOpMicro(const char *mnem, ExtMachInst _machInst,
58            OpClass __opClass)
59                : RiscvMicroInst(mnem, _machInst, __opClass)
60        {}
61
62        std::string generateDisassembly(Addr pc,
63            const SymbolTable *symtab) const;
64    };
65}};
66
67output decoder {{
68    std::string AtomicMemOp::generateDisassembly(Addr pc,
69        const SymbolTable *symtab) const
70    {
71        std::stringstream ss;
72        ss << csprintf("0x%08x", machInst) << ' ';
73        ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", "
74                << regName(_srcRegIdx[1]) << ", ("
75                << regName(_srcRegIdx[0]) << ')';
76        return ss.str();
77    }
78
79    std::string AtomicMemOpMicro::generateDisassembly(Addr pc,
80        const SymbolTable *symtab) const
81    {
82        std::stringstream ss;
83        ss << csprintf("0x%08x", machInst) << ' ' << mnemonic;
84        return ss.str();
85    }
86}};
87
88def template AtomicMemOpDeclare {{
89    /**
90     * Static instruction class for an AtomicMemOp operation
91     */
92    class %(class_name)s : public %(base_class)s
93    {
94      public:
95        // Constructor
96        %(class_name)s(ExtMachInst machInst);
97
98    protected:
99
100        class %(class_name)sLoad : public %(base_class)sMicro
101        {
102          public:
103            // Constructor
104            %(class_name)sLoad(ExtMachInst machInst, %(class_name)s *_p);
105
106            %(BasicExecDeclare)s
107
108            %(EACompDeclare)s
109
110            %(InitiateAccDeclare)s
111
112            %(CompleteAccDeclare)s
113        };
114
115        class %(class_name)sStore : public %(base_class)sMicro
116        {
117          public:
118            // Constructor
119            %(class_name)sStore(ExtMachInst machInst, %(class_name)s *_p);
120
121            %(BasicExecDeclare)s
122
123            %(EACompDeclare)s
124
125            %(InitiateAccDeclare)s
126
127            %(CompleteAccDeclare)s
128        };
129    };
130}};
131
132def template AtomicMemOpMacroConstructor {{
133    %(class_name)s::%(class_name)s(ExtMachInst machInst)
134            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
135    {
136        %(constructor)s;
137        microops = {new %(class_name)sLoad(machInst, this),
138            new %(class_name)sStore(machInst, this)};
139    }
140}};
141
142def template AtomicMemOpLoadConstructor {{
143    %(class_name)s::%(class_name)sLoad::%(class_name)sLoad(
144        ExtMachInst machInst, %(class_name)s *_p)
145            : %(base_class)s("%(mnemonic)s[l]", machInst, %(op_class)s)
146    {
147        %(constructor)s;
148        flags[IsFirstMicroop] = true;
149        flags[IsDelayedCommit] = true;
150        if (AQ)
151            memAccessFlags = Request::ACQUIRE;
152    }
153}};
154
155def template AtomicMemOpStoreConstructor {{
156    %(class_name)s::%(class_name)sStore::%(class_name)sStore(
157        ExtMachInst machInst, %(class_name)s *_p)
158            : %(base_class)s("%(mnemonic)s[s]", machInst, %(op_class)s)
159    {
160        %(constructor)s;
161        flags[IsLastMicroop] = true;
162        flags[IsNonSpeculative] = true;
163        if (RL)
164            memAccessFlags = Request::RELEASE;
165    }
166}};
167
168def template AtomicMemOpMacroDecode {{
169    return new %(class_name)s(machInst);
170}};
171
172def template AtomicMemOpLoadExecute {{
173    Fault %(class_name)s::%(class_name)sLoad::execute(CPU_EXEC_CONTEXT *xc,
174        Trace::InstRecord *traceData) const
175    {
176        Addr EA;
177        Fault fault = NoFault;
178
179        %(op_decl)s;
180        %(op_rd)s;
181        %(ea_code)s;
182
183        if (fault == NoFault) {
184            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
185        }
186
187        if (fault == NoFault) {
188            %(code)s;
189        }
190
191        if (fault == NoFault) {
192            %(op_wb)s;
193        }
194
195        return fault;
196    }
197}};
198
199def template AtomicMemOpStoreExecute {{
200    Fault %(class_name)s::%(class_name)sStore::execute(CPU_EXEC_CONTEXT *xc,
201        Trace::InstRecord *traceData) const
202    {
203        Addr EA;
204        Fault fault = NoFault;
205
206        %(op_decl)s;
207        %(op_rd)s;
208        %(ea_code)s;
209
210        if (fault == NoFault) {
211            %(code)s;
212        }
213
214        if (fault == NoFault) {
215            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
216                nullptr);
217        }
218
219        if (fault == NoFault) {
220            %(op_wb)s;
221        }
222
223        return fault;
224    }
225}};
226
227def template AtomicMemOpLoadEACompExecute {{
228    Fault %(class_name)s::%(class_name)sLoad::eaComp(CPU_EXEC_CONTEXT *xc,
229        Trace::InstRecord *traceData) const
230    {
231        Addr EA;
232        Fault fault = NoFault;
233
234        %(op_decl)s;
235        %(op_rd)s;
236        %(ea_code)s;
237
238        if (fault == NoFault) {
239            %(op_wb)s;
240            xc->setEA(EA);
241        }
242
243        return fault;
244    }
245}};
246
247def template AtomicMemOpStoreEACompExecute {{
248    Fault %(class_name)s::%(class_name)sStore::eaComp(CPU_EXEC_CONTEXT *xc,
249        Trace::InstRecord *traceData) const
250    {
251        Addr EA;
252        Fault fault = NoFault;
253
254        %(op_decl)s;
255        %(op_rd)s;
256        %(ea_code)s;
257
258        if (fault == NoFault) {
259            %(op_wb)s;
260            xc->setEA(EA);
261        }
262
263        return fault;
264    }
265}};
266
267def template AtomicMemOpLoadInitiateAcc {{
268    Fault %(class_name)s::%(class_name)sLoad::initiateAcc(CPU_EXEC_CONTEXT *xc,
269        Trace::InstRecord *traceData) const
270    {
271        Addr EA;
272        Fault fault = NoFault;
273
274        %(op_src_decl)s;
275        %(op_rd)s;
276        %(ea_code)s;
277
278        if (fault == NoFault) {
279            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
280        }
281
282        return fault;
283    }
284}};
285
286def template AtomicMemOpStoreInitiateAcc {{
287    Fault %(class_name)s::%(class_name)sStore::initiateAcc(
288        CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
289    {
290        Addr EA;
291        Fault fault = NoFault;
292
293        %(op_decl)s;
294        %(op_rd)s;
295        %(ea_code)s;
296
297        if (fault == NoFault) {
298            %(code)s;
299        }
300
301        if (fault == NoFault) {
302            fault = writeMemTiming(xc, traceData, Mem, EA, memAccessFlags,
303                nullptr);
304        }
305
306        if (fault == NoFault) {
307            %(op_wb)s;
308        }
309
310        return fault;
311    }
312}};
313
314def template AtomicMemOpLoadCompleteAcc {{
315    Fault %(class_name)s::%(class_name)sLoad::completeAcc(PacketPtr pkt,
316        CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
317    {
318        Fault fault = NoFault;
319
320        %(op_decl)s;
321        %(op_rd)s;
322
323        getMem(pkt, Mem, traceData);
324
325        if (fault == NoFault) {
326            %(code)s;
327        }
328
329        if (fault == NoFault) {
330            %(op_wb)s;
331        }
332
333        return fault;
334    }
335}};
336
337def template AtomicMemOpStoreCompleteAcc {{
338    Fault %(class_name)s::%(class_name)sStore::completeAcc(PacketPtr pkt,
339        CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
340    {
341        return NoFault;
342    }
343}};
344
345def format AtomicMemOp(load_code, store_code, ea_code, load_flags=[],
346        store_flags=[], inst_flags=[]) {{
347    macro_iop = InstObjParams(name, Name, 'AtomicMemOp', ea_code, inst_flags)
348    header_output = AtomicMemOpDeclare.subst(macro_iop)
349    decoder_output = AtomicMemOpMacroConstructor.subst(macro_iop)
350    decode_block = AtomicMemOpMacroDecode.subst(macro_iop)
351    exec_output = ''
352
353    load_inst_flags = makeList(inst_flags) + ["IsMemRef", "IsLoad"]
354    load_iop = InstObjParams(name, Name, 'AtomicMemOpMicro',
355        {'ea_code': ea_code, 'code': load_code}, load_inst_flags)
356    decoder_output += AtomicMemOpLoadConstructor.subst(load_iop)
357    exec_output += AtomicMemOpLoadExecute.subst(load_iop) \
358        + AtomicMemOpLoadEACompExecute.subst(load_iop) \
359        + AtomicMemOpLoadInitiateAcc.subst(load_iop) \
360        + AtomicMemOpLoadCompleteAcc.subst(load_iop)
361
362    store_inst_flags = makeList(inst_flags) + ["IsMemRef", "IsStore"]
363    store_iop = InstObjParams(name, Name, 'AtomicMemOpMicro',
364        {'ea_code': ea_code, 'code': store_code}, store_inst_flags)
365    decoder_output += AtomicMemOpStoreConstructor.subst(store_iop)
366    exec_output += AtomicMemOpStoreExecute.subst(store_iop) \
367        + AtomicMemOpStoreEACompExecute.subst(store_iop) \
368        + AtomicMemOpStoreInitiateAcc.subst(store_iop) \
369        + AtomicMemOpStoreCompleteAcc.subst(store_iop)
370}};
371