Deleted Added
sdiff udiff text old ( 12482:35461496d012 ) new ( 13653:079472978bca )
full compact
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

--- 15 unchanged lines hidden (view full) ---

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// Declaration templates
33def template AtomicMemOpDeclare {{
34 /**
35 * Static instruction class for an AtomicMemOp operation
36 */
37 class %(class_name)s : public %(base_class)s
38 {
39 public:
40 // Constructor
41 %(class_name)s(ExtMachInst machInst);
42
43 protected:
44
45 /*
46 * The main RMW part of an AMO
47 */
48 class %(class_name)sRMW : public %(base_class)sMicro
49 {
50 public:
51 // Constructor
52 %(class_name)sRMW(ExtMachInst machInst, %(class_name)s *_p);
53
54 Fault execute(ExecContext *, Trace::InstRecord *) const override;
55 Fault initiateAcc(ExecContext *,
56 Trace::InstRecord *) const override;
57 Fault completeAcc(PacketPtr, ExecContext *,
58 Trace::InstRecord *) const override;
59 };
60 };
61}};
62
63def template LRSCDeclare {{
64 /**
65 * Static instruction class for an AtomicMemOp operation
66 */
67 class %(class_name)s : public %(base_class)s
68 {
69 public:
70 // Constructor
71 %(class_name)s(ExtMachInst machInst);
72
73 protected:
74
75 class %(class_name)sMicro : public %(base_class)sMicro
76 {
77 public:
78 // Constructor
79 %(class_name)sMicro(ExtMachInst machInst, %(class_name)s *_p);
80
81 Fault execute(ExecContext *, Trace::InstRecord *) const override;
82 Fault initiateAcc(ExecContext *,
83 Trace::InstRecord *) const override;
84 Fault completeAcc(PacketPtr, ExecContext *,
85 Trace::InstRecord *) const override;
86 };
87 };
88}};
89
90// Constructor templates
91def template LRSCMacroConstructor {{
92 %(class_name)s::%(class_name)s(ExtMachInst machInst):
93 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
94 {
95 %(constructor)s;
96
97 StaticInstPtr rel_fence;
98 StaticInstPtr lrsc;
99 StaticInstPtr acq_fence;
100
101 // set up release fence
102 if (RL) {
103 rel_fence = new MemFenceMicro(machInst, No_OpClass);
104 rel_fence->setFlag(IsFirstMicroop);
105 rel_fence->setFlag(IsMemBarrier);
106 rel_fence->setFlag(IsDelayedCommit);
107 }
108
109 // set up atomic rmw op
110 lrsc = new %(class_name)sMicro(machInst, this);
111
112 if (!RL) {
113 lrsc->setFlag(IsFirstMicroop);
114 }
115
116 if (!AQ) {
117 lrsc->setFlag(IsLastMicroop);
118 } else {
119 lrsc->setFlag(IsDelayedCommit);
120 }
121
122 // set up acquire fence
123 if (AQ) {
124 acq_fence = new MemFenceMicro(machInst, No_OpClass);
125 acq_fence->setFlag(IsLastMicroop);
126 acq_fence->setFlag(IsMemBarrier);
127 }
128
129 if (RL && AQ) {
130 microops = {rel_fence, lrsc, acq_fence};
131 } else if (RL) {
132 microops = {rel_fence, lrsc};
133 } else if (AQ) {
134 microops = {lrsc, acq_fence};
135 } else {
136 microops = {lrsc};
137 }
138 }
139}};
140
141def template LRSCMicroConstructor {{
142 %(class_name)s::%(class_name)sMicro::%(class_name)sMicro(
143 ExtMachInst machInst, %(class_name)s *_p)
144 : %(base_class)sMicro("%(mnemonic)s", machInst, %(op_class)s)
145 {
146 %(constructor)s;
147 }
148}};
149
150def template AtomicMemOpMacroConstructor {{
151 %(class_name)s::%(class_name)s(ExtMachInst machInst)
152 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
153 {
154 %(constructor)s;
155
156 StaticInstPtr rel_fence;
157 StaticInstPtr rmw_op;
158 StaticInstPtr acq_fence;
159
160 // set up release fence
161 if (RL) {
162 rel_fence = new MemFenceMicro(machInst, No_OpClass);
163 rel_fence->setFlag(IsFirstMicroop);
164 rel_fence->setFlag(IsMemBarrier);
165 rel_fence->setFlag(IsDelayedCommit);
166 }
167
168 // set up atomic rmw op
169 rmw_op = new %(class_name)sRMW(machInst, this);
170
171 if (!RL) {
172 rmw_op->setFlag(IsFirstMicroop);
173 }
174
175 if (!AQ) {
176 rmw_op->setFlag(IsLastMicroop);
177 } else {
178 rmw_op->setFlag(IsDelayedCommit);
179 }
180
181 // set up acquire fence
182 if (AQ) {
183 acq_fence = new MemFenceMicro(machInst, No_OpClass);
184 acq_fence->setFlag(IsLastMicroop);
185 acq_fence->setFlag(IsMemBarrier);
186 }
187
188 if (RL && AQ) {
189 microops = {rel_fence, rmw_op, acq_fence};
190 } else if (RL) {
191 microops = {rel_fence, rmw_op};
192 } else if (AQ) {
193 microops = {rmw_op, acq_fence};
194 } else {
195 microops = {rmw_op};
196 }
197 }
198}};
199
200def template AtomicMemOpRMWConstructor {{
201 %(class_name)s::%(class_name)sRMW::%(class_name)sRMW(
202 ExtMachInst machInst, %(class_name)s *_p)
203 : %(base_class)s("%(mnemonic)s[l]", machInst, %(op_class)s)
204 {
205 %(constructor)s;
206
207 // overwrite default flags
208 flags[IsMemRef] = true;
209 flags[IsLoad] = false;
210 flags[IsStore] = false;
211 flags[IsAtomic] = true;
212 }
213}};
214
215// execute() templates
216
217def template LoadReservedExecute {{
218 Fault
219 %(class_name)s::%(class_name)sMicro::execute(
220 ExecContext *xc, Trace::InstRecord *traceData) const
221 {
222 Addr EA;
223 Fault fault = NoFault;
224
225 %(op_decl)s;
226 %(op_rd)s;
227 %(ea_code)s;
228
229 if (fault == NoFault) {
230 fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
231 %(memacc_code)s;
232 }
233
234 if (fault == NoFault) {
235 %(op_wb)s;
236 }
237
238 return fault;
239 }
240}};
241
242def template StoreCondExecute {{
243 Fault %(class_name)s::%(class_name)sMicro::execute(ExecContext *xc,
244 Trace::InstRecord *traceData) const
245 {
246 Addr EA;
247 Fault fault = NoFault;
248 uint64_t result;
249
250 %(op_decl)s;
251 %(op_rd)s;

--- 18 unchanged lines hidden (view full) ---

270 if (fault == NoFault) {
271 %(op_wb)s;
272 }
273
274 return fault;
275 }
276}};
277
278def template AtomicMemOpRMWExecute {{
279 Fault %(class_name)s::%(class_name)sRMW::execute(ExecContext *xc,
280 Trace::InstRecord *traceData) const
281 {
282 Addr EA;
283 Fault fault = NoFault;
284
285 %(op_decl)s;
286 %(op_rd)s;
287 %(ea_code)s;
288 %(amoop_code)s;
289
290 assert(amo_op);
291
292 if (fault == NoFault) {
293 fault = amoMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
294 amo_op);
295 %(memacc_code)s;
296 }
297
298 if (fault == NoFault) {
299 %(postacc_code)s;
300 }
301
302 if (fault == NoFault) {
303 %(op_wb)s;
304 }
305
306 return fault;
307 }
308}};
309
310// initiateAcc() templates
311
312def template LoadReservedInitiateAcc {{
313 Fault
314 %(class_name)s::%(class_name)sMicro::initiateAcc(ExecContext *xc,
315 Trace::InstRecord *traceData) const
316 {
317 Addr EA;
318 Fault fault = NoFault;
319
320 %(op_src_decl)s;
321 %(op_rd)s;
322 %(ea_code)s;
323
324 if (fault == NoFault) {
325 fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
326 }
327
328 return fault;
329 }
330}};
331
332def template StoreCondInitiateAcc {{
333 Fault
334 %(class_name)s::%(class_name)sMicro::initiateAcc(ExecContext *xc,
335 Trace::InstRecord *traceData) const
336 {
337 Addr EA;
338 Fault fault = NoFault;
339
340 %(op_decl)s;
341 %(op_rd)s;
342 %(ea_code)s;
343
344 if (fault == NoFault) {
345 %(memacc_code)s;
346 }
347
348 if (fault == NoFault) {
349 fault = writeMemTiming(xc, traceData, Mem, EA,
350 memAccessFlags, nullptr);
351 }
352
353 if (fault == NoFault) {
354 %(op_wb)s;
355 }
356
357 return fault;
358 }
359}};
360
361def template AtomicMemOpRMWInitiateAcc {{
362 Fault
363 %(class_name)s::%(class_name)sRMW::initiateAcc(ExecContext *xc,
364 Trace::InstRecord *traceData) const
365 {
366 Addr EA;
367 Fault fault = NoFault;
368
369 %(op_src_decl)s;
370 %(op_rd)s;
371 %(ea_code)s;
372 %(amoop_code)s;
373
374 assert(amo_op);
375
376 if (fault == NoFault) {
377 fault = initiateMemAMO(xc, traceData, EA, Mem, memAccessFlags,
378 amo_op);
379 }
380
381 return fault;
382 }
383}};
384
385// completeAcc() templates
386
387def template LoadReservedCompleteAcc {{
388 Fault
389 %(class_name)s::%(class_name)sMicro::completeAcc(PacketPtr pkt,
390 ExecContext *xc, Trace::InstRecord *traceData) const
391 {
392 Fault fault = NoFault;
393
394 %(op_decl)s;
395 %(op_rd)s;
396
397 getMem(pkt, Mem, traceData);
398
399 if (fault == NoFault) {
400 %(memacc_code)s;
401 }
402
403 if (fault == NoFault) {
404 %(op_wb)s;
405 }
406
407 return fault;
408 }
409}};
410
411def template StoreCondCompleteAcc {{
412 Fault %(class_name)s::%(class_name)sMicro::completeAcc(Packet *pkt,
413 ExecContext *xc, Trace::InstRecord *traceData) const
414 {
415 Fault fault = NoFault;
416
417 %(op_dest_decl)s;
418
419 // RISC-V has the opposite convention gem5 has for success flags,
420 // so we invert the result here.
421 uint64_t result = !pkt->req->getExtraData();

--- 5 unchanged lines hidden (view full) ---

427 if (fault == NoFault) {
428 %(op_wb)s;
429 }
430
431 return fault;
432 }
433}};
434
435def template AtomicMemOpRMWCompleteAcc {{
436 Fault %(class_name)s::%(class_name)sRMW::completeAcc(Packet *pkt,
437 ExecContext *xc, Trace::InstRecord *traceData) const
438 {
439 Fault fault = NoFault;
440
441 %(op_decl)s;
442 %(op_rd)s;
443
444 getMem(pkt, Mem, traceData);
445
446 if (fault == NoFault) {
447 %(memacc_code)s;
448 }
449
450 if (fault == NoFault) {
451 %(op_wb)s;
452 }
453
454 return fault;
455 }
456}};
457
458// LR/SC/AMO decode formats
459
460def format LoadReserved(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
461 mem_flags=[], inst_flags=[]) {{
462 macro_ea_code = ''
463 macro_inst_flags = []
464 macro_iop = InstObjParams(name, Name, 'LoadReserved', macro_ea_code,
465 macro_inst_flags)
466 header_output = LRSCDeclare.subst(macro_iop)
467 decoder_output = LRSCMacroConstructor.subst(macro_iop)
468 decode_block = BasicDecode.subst(macro_iop)
469
470 exec_output = ''
471
472 mem_flags = makeList(mem_flags)
473 inst_flags = makeList(inst_flags)
474 iop = InstObjParams(name, Name, 'LoadReserved',
475 {'ea_code': ea_code, 'memacc_code': memacc_code,
476 'postacc_code': postacc_code}, inst_flags)
477 iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
478 '|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'
479
480 decoder_output += LRSCMicroConstructor.subst(iop)
481 decode_block += BasicDecode.subst(iop)
482 exec_output += LoadReservedExecute.subst(iop) \
483 + LoadReservedInitiateAcc.subst(iop) \
484 + LoadReservedCompleteAcc.subst(iop)
485}};
486
487def format StoreCond(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
488 mem_flags=[], inst_flags=[]) {{
489 macro_ea_code = ''
490 macro_inst_flags = []
491 macro_iop = InstObjParams(name, Name, 'StoreCond', macro_ea_code,
492 macro_inst_flags)
493 header_output = LRSCDeclare.subst(macro_iop)
494 decoder_output = LRSCMacroConstructor.subst(macro_iop)
495 decode_block = BasicDecode.subst(macro_iop)
496
497 exec_output = ''
498
499 mem_flags = makeList(mem_flags)
500 inst_flags = makeList(inst_flags)
501 iop = InstObjParams(name, Name, 'StoreCond',
502 {'ea_code': ea_code, 'memacc_code': memacc_code,
503 'postacc_code': postacc_code}, inst_flags)
504 iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
505 '|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'
506
507 decoder_output += LRSCMicroConstructor.subst(iop)
508 decode_block += BasicDecode.subst(iop)
509 exec_output += StoreCondExecute.subst(iop) \
510 + StoreCondInitiateAcc.subst(iop) \
511 + StoreCondCompleteAcc.subst(iop)
512}};
513
514def format AtomicMemOp(memacc_code, amoop_code, postacc_code={{ }},
515 ea_code={{EA = Rs1;}}, mem_flags=[], inst_flags=[]) {{
516 macro_ea_code = ''
517 macro_inst_flags = []
518 macro_iop = InstObjParams(name, Name, 'AtomicMemOp', macro_ea_code,
519 macro_inst_flags)
520 header_output = AtomicMemOpDeclare.subst(macro_iop)
521 decoder_output = AtomicMemOpMacroConstructor.subst(macro_iop)
522 decode_block = BasicDecode.subst(macro_iop)
523
524 exec_output = ''
525
526 rmw_mem_flags = makeList(mem_flags)
527 rmw_inst_flags = makeList(inst_flags)
528 rmw_iop = InstObjParams(name, Name, 'AtomicMemOpMicro',
529 {'ea_code': ea_code,
530 'memacc_code': memacc_code,
531 'postacc_code': postacc_code,
532 'amoop_code': amoop_code},
533 rmw_inst_flags)
534
535 rmw_iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
536 '|'.join(['Request::%s' % flag for flag in rmw_mem_flags]) + ';'
537
538 decoder_output += AtomicMemOpRMWConstructor.subst(rmw_iop)
539 decode_block += BasicDecode.subst(rmw_iop)
540 exec_output += AtomicMemOpRMWExecute.subst(rmw_iop) \
541 + AtomicMemOpRMWInitiateAcc.subst(rmw_iop) \
542 + AtomicMemOpRMWCompleteAcc.subst(rmw_iop)
543}};