sve_mem.isa revision 14028:44edf7dbe672
1// Copyright (c) 2017-2018 ARM Limited
2// All rights reserved
3//
4// The license below extends only to copyright in the software and shall
5// not be construed as granting a license to any other intellectual
6// property including but not limited to intellectual property relating
7// to a hardware implementation of the functionality of the software
8// licensed hereunder.  You may use the software subject to the license
9// terms below provided that you ensure that this notice is replicated
10// unmodified and in its entirety in all distributions of the software,
11// modified or unmodified, in source code or in binary form.
12//
13// Redistribution and use in source and binary forms, with or without
14// modification, are permitted provided that the following conditions are
15// met: redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer;
17// redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution;
20// neither the name of the copyright holders nor the names of its
21// contributors may be used to endorse or promote products derived from
22// this software without specific prior written permission.
23//
24// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35//
36// Authors: Giacomo Gabrielli
37
38def template SveMemFillSpillOpDeclare {{
39    class %(class_name)s : public %(base_class)s
40    {
41      protected:
42        typedef uint8_t TPElem;
43        typedef uint8_t RegElemType;
44        typedef uint8_t MemElemType;
45
46      public:
47        %(class_name)s(ExtMachInst machInst,
48            IntRegIndex _dest, IntRegIndex _base, uint64_t _imm)
49            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
50                _dest, _base, _imm)
51        {
52            %(constructor)s;
53        }
54
55        Fault execute(ExecContext *, Trace::InstRecord *) const;
56        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
57        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
58
59        virtual void
60        annotateFault(ArmFault *fault) {
61            %(fa_code)s
62        }
63    };
64}};
65
66def template SveContigMemSSOpDeclare {{
67    %(tpl_header)s
68    class %(class_name)s : public %(base_class)s
69    {
70      protected:
71        typedef RegElemType TPElem;
72
73      public:
74        %(class_name)s(const char* mnem, ExtMachInst machInst,
75            IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
76            IntRegIndex _offset)
77            : %(base_class)s(mnem, machInst, %(op_class)s,
78                _dest, _gp, _base, _offset)
79        {
80            %(constructor)s;
81        }
82
83        Fault execute(ExecContext *, Trace::InstRecord *) const;
84        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
85        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
86
87        virtual void
88        annotateFault(ArmFault *fault) {
89            %(fa_code)s
90        }
91    };
92}};
93
94def template SveContigMemSIOpDeclare {{
95    %(tpl_header)s
96    class %(class_name)s : public %(base_class)s
97    {
98      protected:
99        typedef RegElemType TPElem;
100
101      public:
102        %(class_name)s(const char* mnem, ExtMachInst machInst,
103            IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
104            uint64_t _imm)
105            : %(base_class)s(mnem, machInst, %(op_class)s,
106                _dest, _gp, _base, _imm)
107        {
108            %(constructor)s;
109        }
110
111        Fault execute(ExecContext *, Trace::InstRecord *) const;
112        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
113        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
114
115        virtual void
116        annotateFault(ArmFault *fault) {
117            %(fa_code)s
118        }
119    };
120}};
121
122def template SveContigMemExecDeclare {{
123    template
124    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *,
125        Trace::InstRecord *) const;
126
127    template
128    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *,
129        Trace::InstRecord *) const;
130
131    template
132    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr,
133        ExecContext *, Trace::InstRecord *) const;
134}};
135
136def template SveContigLoadExecute {{
137    %(tpl_header)s
138    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
139        Trace::InstRecord *traceData) const
140    {
141        Addr EA;
142        Fault fault = NoFault;
143        bool aarch64 M5_VAR_USED = true;
144        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
145            xc->tcBase());
146
147        %(op_decl)s;
148        %(op_rd)s;
149        %(ea_code)s;
150
151        TheISA::VecRegContainer memData;
152        auto memDataView = memData.as<MemElemType>();
153
154        if (fault == NoFault) {
155            fault = xc->readMem(EA, memData.raw_ptr<uint8_t>(), memAccessSize,
156                this->memAccessFlags);
157            %(memacc_code)s;
158        }
159
160        if (fault == NoFault) {
161            %(op_wb)s;
162        }
163
164        return fault;
165    }
166}};
167
168def template SveContigLoadInitiateAcc {{
169    %(tpl_header)s
170    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
171        Trace::InstRecord *traceData) const
172    {
173        Addr EA;
174        Fault fault = NoFault;
175        bool aarch64 M5_VAR_USED = true;
176        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
177            xc->tcBase());
178
179        %(op_src_decl)s;
180        %(op_rd)s;
181
182        %(ea_code)s;
183
184        if (fault == NoFault) {
185            fault = xc->initiateMemRead(EA, memAccessSize,
186                this->memAccessFlags);
187        }
188
189        return fault;
190    }
191}};
192
193def template SveContigLoadCompleteAcc {{
194    %(tpl_header)s
195    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
196        ExecContext *xc, Trace::InstRecord *traceData) const
197    {
198        Fault fault = NoFault;
199        bool aarch64 M5_VAR_USED = true;
200        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
201            xc->tcBase());
202
203        %(op_decl)s;
204        %(op_rd)s;
205
206        TheISA::VecRegContainer memData;
207        auto memDataView = memData.as<MemElemType>();
208
209        memcpy(memData.raw_ptr<uint8_t>(), pkt->getPtr<uint8_t>(),
210            pkt->getSize());
211
212        if (fault == NoFault) {
213            %(memacc_code)s;
214        }
215
216        if (fault == NoFault) {
217            %(op_wb)s;
218        }
219
220        return fault;
221    }
222}};
223
224def template SveContigStoreExecute {{
225    %(tpl_header)s
226    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
227        Trace::InstRecord *traceData) const
228    {
229        Addr EA;
230        Fault fault = NoFault;
231        bool aarch64 M5_VAR_USED = true;
232        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
233            xc->tcBase());
234
235        %(op_decl)s;
236        %(op_rd)s;
237        %(ea_code)s;
238
239        TheISA::VecRegContainer memData;
240        auto memDataView = memData.as<MemElemType>();
241
242        %(wren_code)s;
243
244        if (fault == NoFault) {
245            %(memacc_code)s;
246        }
247
248        if (fault == NoFault) {
249            fault = xc->writeMem(memData.raw_ptr<uint8_t>(), memAccessSize, EA,
250                this->memAccessFlags, NULL, wrEn);
251        }
252
253        if (fault == NoFault) {
254            %(op_wb)s;
255        }
256
257        return fault;
258    }
259}};
260
261def template SveContigStoreInitiateAcc {{
262    %(tpl_header)s
263    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
264        Trace::InstRecord *traceData) const
265    {
266        Addr EA;
267        Fault fault = NoFault;
268        bool aarch64 M5_VAR_USED = true;
269        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
270            xc->tcBase());
271
272        %(op_decl)s;
273        %(op_rd)s;
274        %(ea_code)s;
275
276        TheISA::VecRegContainer memData;
277        auto memDataView = memData.as<MemElemType>();
278
279        %(wren_code)s;
280
281        if (fault == NoFault) {
282            %(memacc_code)s;
283        }
284
285        if (fault == NoFault) {
286            fault = xc->writeMem(memData.raw_ptr<uint8_t>(), memAccessSize, EA,
287                this->memAccessFlags, NULL, wrEn);
288        }
289
290        return fault;
291    }
292}};
293
294def template SveContigStoreCompleteAcc {{
295    %(tpl_header)s
296    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
297        ExecContext *xc, Trace::InstRecord *traceData) const
298    {
299        return NoFault;
300    }
301}};
302
303def template SveLoadAndReplExecute {{
304    %(tpl_header)s
305    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
306        Trace::InstRecord *traceData) const
307    {
308        Addr EA;
309        Fault fault = NoFault;
310        bool aarch64 M5_VAR_USED = true;
311        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
312            xc->tcBase());
313
314        %(op_decl)s;
315        %(op_rd)s;
316        %(ea_code)s;
317
318        MemElemType memData;
319
320        if (fault == NoFault) {
321            fault = readMemAtomic(xc, traceData, EA, memData,
322                this->memAccessFlags);
323            %(memacc_code)s;
324        }
325
326        if (fault == NoFault) {
327            %(op_wb)s;
328        }
329
330        return fault;
331    }
332}};
333
334def template SveLoadAndReplInitiateAcc {{
335    %(tpl_header)s
336    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
337        Trace::InstRecord *traceData) const
338    {
339        Addr EA;
340        Fault fault = NoFault;
341        bool aarch64 M5_VAR_USED = true;
342
343        %(op_src_decl)s;
344        %(op_rd)s;
345
346        %(ea_code)s;
347
348        MemElemType memData;
349
350        if (fault == NoFault) {
351            fault = initiateMemRead(xc, traceData, EA, memData,
352                this->memAccessFlags);
353        }
354
355        return fault;
356    }
357}};
358
359def template SveLoadAndReplCompleteAcc {{
360    %(tpl_header)s
361    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
362        ExecContext *xc, Trace::InstRecord *traceData) const
363    {
364        Fault fault = NoFault;
365        bool aarch64 M5_VAR_USED = true;
366        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
367            xc->tcBase());
368
369        %(op_decl)s;
370        %(op_rd)s;
371
372        MemElemType memData;
373        getMem(pkt, memData, traceData);
374
375        if (fault == NoFault) {
376            %(memacc_code)s;
377        }
378
379        if (fault == NoFault) {
380            %(op_wb)s;
381        }
382
383        return fault;
384    }
385}};
386
387def template SveIndexedMemVIMicroopDeclare {{
388    %(tpl_header)s
389    class %(class_name)s : public %(base_class)s
390    {
391      protected:
392        typedef RegElemType TPElem;
393
394        IntRegIndex dest;
395        IntRegIndex gp;
396        IntRegIndex base;
397        uint64_t imm;
398
399        int elemIndex;
400        int numElems;
401
402        unsigned memAccessFlags;
403
404      public:
405        %(class_name)s(const char* mnem, ExtMachInst machInst,
406            OpClass __opClass, IntRegIndex _dest, IntRegIndex _gp,
407            IntRegIndex _base, uint64_t _imm, int _elemIndex, int _numElems)
408            : %(base_class)s(mnem, machInst, %(op_class)s),
409              dest(_dest), gp(_gp), base(_base), imm(_imm),
410              elemIndex(_elemIndex), numElems(_numElems),
411              memAccessFlags(ArmISA::TLB::AllowUnaligned |
412                             ArmISA::TLB::MustBeOne)
413        {
414            %(constructor)s;
415            if (_opClass == MemReadOp && elemIndex == 0) {
416                // The first micro-op is responsible for pinning the
417                // destination register
418                _destRegIdx[0].setNumPinnedWrites(numElems - 1);
419            }
420        }
421
422        Fault execute(ExecContext *, Trace::InstRecord *) const;
423        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
424        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
425
426        virtual void
427        annotateFault(ArmFault *fault)
428        {
429            %(fa_code)s
430        }
431
432        std::string
433        generateDisassembly(Addr pc, const SymbolTable *symtab) const
434        {
435            // TODO: add suffix to transfer register
436            std::stringstream ss;
437            printMnemonic(ss, "", false);
438            ccprintf(ss, "{");
439            printVecReg(ss, dest, true);
440            ccprintf(ss, "}, ");
441            printVecPredReg(ss, gp);
442            if (_opClass == MemReadOp) {
443                ccprintf(ss, "/z");
444            }
445            ccprintf(ss, ", [");
446            printVecReg(ss, base, true);
447            if (imm != 0) {
448                ccprintf(ss, ", #%d", imm * sizeof(MemElemType));
449            }
450            ccprintf(ss, "] (uop elem %d tfer)", elemIndex);
451            return ss.str();
452        }
453    };
454}};
455
456def template SveIndexedMemSVMicroopDeclare {{
457    %(tpl_header)s
458    class %(class_name)s : public %(base_class)s
459    {
460      protected:
461        typedef RegElemType TPElem;
462
463        IntRegIndex dest;
464        IntRegIndex gp;
465        IntRegIndex base;
466        IntRegIndex offset;
467
468        bool offsetIs32;
469        bool offsetIsSigned;
470        bool offsetIsScaled;
471
472        int elemIndex;
473        int numElems;
474
475        unsigned memAccessFlags;
476
477      public:
478        %(class_name)s(const char* mnem, ExtMachInst machInst,
479            OpClass __opClass, IntRegIndex _dest, IntRegIndex _gp,
480            IntRegIndex _base, IntRegIndex _offset, bool _offsetIs32,
481            bool _offsetIsSigned, bool _offsetIsScaled, int _elemIndex,
482            int _numElems)
483            : %(base_class)s(mnem, machInst, %(op_class)s),
484              dest(_dest), gp(_gp), base(_base), offset(_offset),
485              offsetIs32(_offsetIs32), offsetIsSigned(_offsetIsSigned),
486              offsetIsScaled(_offsetIsScaled), elemIndex(_elemIndex),
487              numElems(_numElems),
488              memAccessFlags(ArmISA::TLB::AllowUnaligned |
489                             ArmISA::TLB::MustBeOne)
490        {
491            %(constructor)s;
492            if (_opClass == MemReadOp && elemIndex == 0) {
493                // The first micro-op is responsible for pinning the
494                // destination register
495                _destRegIdx[0].setNumPinnedWrites(numElems - 1);
496            }
497        }
498
499        Fault execute(ExecContext *, Trace::InstRecord *) const;
500        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
501        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
502
503        virtual void
504        annotateFault(ArmFault *fault)
505        {
506            %(fa_code)s
507        }
508
509        std::string
510        generateDisassembly(Addr pc, const SymbolTable *symtab) const
511        {
512            // TODO: add suffix to transfer and base registers
513            std::stringstream ss;
514            printMnemonic(ss, "", false);
515            ccprintf(ss, "{");
516            printVecReg(ss, dest, true);
517            ccprintf(ss, "}, ");
518            printVecPredReg(ss, gp);
519            if (_opClass == MemReadOp) {
520                ccprintf(ss, "/z");
521            }
522            ccprintf(ss, ", [");
523            printIntReg(ss, base);
524            ccprintf(ss, ", ");
525            printVecReg(ss, offset, true);
526            ccprintf(ss, "] (uop elem %d tfer)", elemIndex);
527            return ss.str();
528        }
529    };
530}};
531
532def template SveGatherLoadMicroopExecute {{
533    %(tpl_header)s
534    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
535        Trace::InstRecord *traceData) const
536    {
537        Addr EA;
538        Fault fault = NoFault;
539        bool aarch64 M5_VAR_USED = true;
540
541        %(op_decl)s;
542        %(op_rd)s;
543        %(ea_code)s;
544
545        MemElemType memData;
546
547        if (%(pred_check_code)s) {
548            fault = readMemAtomic(xc, traceData, EA, memData,
549                this->memAccessFlags);
550        }
551
552        if (fault == NoFault) {
553            %(memacc_code)s;
554            %(op_wb)s;
555        }
556
557        return fault;
558    }
559}};
560
561def template SveGatherLoadMicroopInitiateAcc {{
562    %(tpl_header)s
563    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
564        Trace::InstRecord *traceData) const
565    {
566        Addr EA;
567        Fault fault = NoFault;
568        bool aarch64 M5_VAR_USED = true;
569
570        %(op_src_decl)s;
571        %(op_rd)s;
572        %(ea_code)s;
573
574        MemElemType memData;
575
576        if (%(pred_check_code)s) {
577            fault = initiateMemRead(xc, traceData, EA, memData,
578                this->memAccessFlags);
579        } else {
580            xc->setMemAccPredicate(false);
581        }
582
583        return fault;
584    }
585}};
586
587def template SveGatherLoadMicroopCompleteAcc {{
588    %(tpl_header)s
589    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
590        ExecContext *xc, Trace::InstRecord *traceData) const
591    {
592        Fault fault = NoFault;
593        bool aarch64 M5_VAR_USED = true;
594
595        %(op_decl)s;
596        %(op_rd)s;
597
598        MemElemType memData = 0;
599        if (%(pred_check_code)s) {
600            getMem(pkt, memData, traceData);
601        }
602
603        if (fault == NoFault) {
604            %(memacc_code)s;
605        }
606
607        if (fault == NoFault) {
608            %(op_wb)s;
609        }
610
611        return fault;
612    }
613}};
614
615def template SveScatterStoreMicroopExecute {{
616    %(tpl_header)s
617    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
618        Trace::InstRecord *traceData) const
619    {
620        Addr EA;
621        Fault fault = NoFault;
622        bool aarch64 M5_VAR_USED = true;
623
624        %(op_decl)s;
625        %(op_rd)s;
626        %(ea_code)s;
627
628        MemElemType memData;
629        %(memacc_code)s;
630
631        if (%(pred_check_code)s) {
632            fault = writeMemAtomic(xc, traceData, memData, EA,
633                                   this->memAccessFlags, NULL);
634        }
635
636        if (fault == NoFault) {
637            %(op_wb)s;
638        }
639
640        return fault;
641    }
642}};
643
644def template SveScatterStoreMicroopInitiateAcc {{
645    %(tpl_header)s
646    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
647        Trace::InstRecord *traceData) const
648    {
649        Addr EA;
650        Fault fault = NoFault;
651        bool aarch64 M5_VAR_USED = true;
652
653        %(op_decl)s;
654        %(op_rd)s;
655        %(ea_code)s;
656
657        MemElemType memData;
658        %(memacc_code)s;
659
660        if (%(pred_check_code)s) {
661            fault = writeMemTiming(xc, traceData, memData, EA,
662                                   this->memAccessFlags, NULL);
663        } else {
664            xc->setPredicate(false);
665        }
666
667        return fault;
668    }
669}};
670
671def template SveScatterStoreMicroopCompleteAcc {{
672    %(tpl_header)s
673    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
674        ExecContext *xc, Trace::InstRecord *traceData) const
675    {
676        return NoFault;
677    }
678}};
679
680def template SveGatherLoadCpySrcVecMicroopDeclare {{
681    class SveGatherLoadCpySrcVecMicroop : public MicroOp
682    {
683      protected:
684        IntRegIndex op1;
685
686        StaticInst *macroOp;
687
688      public:
689        SveGatherLoadCpySrcVecMicroop(const char* mnem, ExtMachInst machInst,
690            IntRegIndex _op1, StaticInst *_macroOp)
691            : MicroOp(mnem, machInst, SimdAluOp), op1(_op1), macroOp(_macroOp)
692        {
693            %(constructor)s;
694        }
695
696        Fault execute(ExecContext *, Trace::InstRecord *) const;
697
698        std::string
699        generateDisassembly(Addr pc, const SymbolTable *symtab) const
700        {
701            std::stringstream ss;
702            ccprintf(ss, "%s", macroOp->disassemble(pc, symtab));
703            ccprintf(ss, " (uop src vec cpy)");
704            return ss.str();
705        }
706    };
707}};
708
709def template SveGatherLoadCpySrcVecMicroopExecute {{
710    Fault SveGatherLoadCpySrcVecMicroop::execute(ExecContext *xc,
711            Trace::InstRecord *traceData) const
712    {
713        Fault fault = NoFault;
714        %(op_decl)s;
715        %(op_rd)s;
716
717        %(code)s;
718        if (fault == NoFault)
719        {
720            %(op_wb)s;
721        }
722
723        return fault;
724    }
725}};
726