gem5  v22.1.0.0
thread_context.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright 2019 Google, Inc.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions are
18  * met: redistributions of source code must retain the above copyright
19  * notice, this list of conditions and the following disclaimer;
20  * redistributions in binary form must reproduce the above copyright
21  * notice, this list of conditions and the following disclaimer in the
22  * documentation and/or other materials provided with the distribution;
23  * neither the name of the copyright holders nor the names of its
24  * contributors may be used to endorse or promote products derived from
25  * this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  */
39 
41 
42 #include <cstdint>
43 #include <cstring>
44 #include <utility>
45 #include <vector>
46 
49 #include "arch/arm/regs/vec.hh"
50 #include "arch/arm/system.hh"
51 #include "arch/arm/utility.hh"
52 #include "base/logging.hh"
53 #include "iris/detail/IrisCppAdapter.h"
54 #include "iris/detail/IrisObjects.h"
57 #include "sim/pseudo_inst.hh"
58 
59 namespace gem5
60 {
61 
62 namespace Iris
63 {
64 
65 void
67 {
68  bool enabled = false;
69  call().perInstanceExecution_getState(_instId, enabled);
71 
72  suspend();
73 
74  call().memory_getMemorySpaces(_instId, memorySpaces);
75  for (const auto &space: memorySpaces) {
76  memorySpaceIds.emplace(
77  Iris::CanonicalMsn(space.canonicalMsn), space.spaceId);
78  }
79  call().memory_getUsefulAddressTranslations(_instId, translations);
80 
81  typedef ThreadContext Self;
82  iris::EventSourceInfo evSrcInfo;
83 
84  client.registerEventCallback<Self, &Self::breakpointHit>(
85  this, "ec_IRIS_BREAKPOINT_HIT",
86  "Handle hitting a breakpoint", "Iris::ThreadContext");
87  call().event_getEventSource(_instId, evSrcInfo, "IRIS_BREAKPOINT_HIT");
88  call().eventStream_create(_instId, breakpointEventStreamId,
89  evSrcInfo.evSrcId, client.getInstId());
90 
91  for (auto it = bps.begin(); it != bps.end(); it++)
92  installBp(it);
93 
94  client.registerEventCallback<Self, &Self::semihostingEvent>(
95  this, "ec_IRIS_SEMIHOSTING_CALL_EXTENSION",
96  "Handle a semihosting call", "Iris::ThreadContext");
97  call().event_getEventSource(_instId, evSrcInfo,
98  "IRIS_SEMIHOSTING_CALL_EXTENSION");
99  call().eventStream_create(_instId, semihostingEventStreamId,
100  evSrcInfo.evSrcId, client.getInstId(),
101  // Set all arguments to their defaults, except syncEc which is
102  // changed to true.
103  nullptr, "", false, 0, nullptr, false, false, true);
104 }
105 
106 iris::ResourceId
108  const ResourceMap &resources, const std::string &name)
109 {
110  return resources.at(name).rscId;
111 }
112 
113 void
115  ResourceIds &ids, const ResourceMap &resources,
116  const IdxNameMap &idx_names)
117 {
118  for (const auto &idx_name: idx_names) {
119  int idx = idx_name.first;
120  const std::string &name = idx_name.second;
121 
122  if (idx >= ids.size())
123  ids.resize(idx + 1, iris::IRIS_UINT64_MAX);
124 
125  ids[idx] = extractResourceId(resources, name);
126  }
127 }
128 
129 iris::MemorySpaceId
131 {
132  auto it = memorySpaceIds.find(msn);
133  return it == memorySpaceIds.end() ? iris::IRIS_UINT64_MAX : it->second;
134 }
135 
136 void
138 {
139  Tick now = 0;
140 
141  while (true) {
142  if (comInstEventQueue.empty()) {
143  // Set to 0 to deactivate stepping.
144  call().step_setup(_instId, 0, "instruction");
145  break;
146  }
147 
149  if (!now)
150  now = getCurrentInstCount();
151 
152  if (next <= now) {
154  // Start over now that comInstEventQueue has likely changed.
155  continue;
156  }
157 
158  // Set to the number of instructions still to step through.
159  Tick remaining = next - now;
160  call().step_setup(_instId, remaining, "instruction");
161  break;
162  }
163 }
164 
167 {
168  auto pc_it = bps.find(pc);
169 
170  if (pc_it != bps.end())
171  return pc_it;
172 
173  auto res = bps.emplace(std::make_pair(pc, new BpInfo(pc)));
174  panic_if(!res.second, "Inserting breakpoint failed.");
175  return res.first;
176 }
177 
178 void
180 {
181  Addr pc = it->second->pc;
182  const auto &space_ids = getBpSpaceIds();
183  for (auto sid: space_ids) {
184  BpId id;
185  call().breakpoint_set_code(_instId, id, pc, sid, 0);
186  it->second->ids.push_back(id);
187  }
188 }
189 
190 void
192 {
193  for (auto id: it->second->ids)
194  call().breakpoint_delete(_instId, id);
195  it->second->clearIds();
196 }
197 
198 void
200 {
201  panic_if(!it->second->empty(),
202  "BP info still had events associated with it.");
203 
204  if (it->second->validIds())
205  uninstallBp(it);
206 
207  bps.erase(it);
208 }
209 
210 iris::IrisErrorCode
212  uint64_t esId, const iris::IrisValueMap &fields, uint64_t time,
213  uint64_t sInstId, bool syncEc, std::string &error_message_out)
214 {
215  const std::string &event = fields.at("EVENT").getString();
216  const iris::InstanceId id = fields.at("INST_ID").getU64();
217  const std::string &name = fields.at("INST_NAME").getString();
218 
219  if (name != "component." + _irisPath)
220  return iris::E_ok;
221 
222  if (event == "added")
223  _instId = id;
224  else if (event == "removed")
225  _instId = iris::IRIS_UINT64_MAX;
226  else
227  panic("Unrecognized event type %s", event);
228 
229  return iris::E_ok;
230 }
231 
232 iris::IrisErrorCode
234  uint64_t esId, const iris::IrisValueMap &fields, uint64_t time,
235  uint64_t sInstId, bool syncEc, std::string &error_message_out)
236 {
238  call().resource_getList(_instId, resources);
239 
240  std::map<iris::ResourceId, const iris::ResourceInfo *>
241  idToResource;
242  for (const auto &resource: resources) {
243  idToResource[resource.rscId] = &resource;
244  }
245  ResourceMap resourceMap;
246  for (const auto &resource: resources) {
247  std::string name = resource.name;
248  iris::ResourceId parentId = resource.parentRscId;
249  while (parentId != iris::IRIS_UINT64_MAX) {
250  const auto *parent = idToResource[parentId];
251  name = parent->name + "." + name;
252  parentId = parent->parentRscId;
253  }
254  resourceMap[name] = resource;
255  }
256 
257  initFromIrisInstance(resourceMap);
258 
259  return iris::E_ok;
260 }
261 
262 iris::IrisErrorCode
264  uint64_t esId, const iris::IrisValueMap &fields, uint64_t time,
265  uint64_t sInstId, bool syncEc, std::string &error_message_out)
266 {
267  if (fields.at("RUNNING").getAsBool()) {
268  // If this is just simulation time starting up, don't do anything.
269  return iris::E_ok;
270  }
271 
272  // If simulation time has stopped for any reason, IRIS helpfully clears
273  // all stepping counters and we need to set them back. We might also need
274  // to service events based on the current number of executed instructions.
276 
277  // Restart simulation time to make sure things progress once we give
278  // control back.
279  call().simulationTime_run(iris::IrisInstIdSimulationEngine);
280 
281  return iris::E_ok;
282 }
283 
284 iris::IrisErrorCode
286  uint64_t esId, const iris::IrisValueMap &fields, uint64_t time,
287  uint64_t sInstId, bool syncEc, std::string &error_message_out)
288 {
289  Addr pc = fields.at("PC").getU64();
290 
291  auto it = getOrAllocBp(pc);
292 
293  std::shared_ptr<BpInfo::EventList> events = it->second->events;
294  auto e_it = events->begin();
295  while (e_it != events->end()) {
296  PCEvent *e = *e_it;
297  // Advance e_it here since e might remove itself from the list.
298  e_it++;
299  e->process(this);
300  }
301 
302  return iris::E_ok;
303 }
304 
305 iris::IrisErrorCode
307  uint64_t esId, const iris::IrisValueMap &fields, uint64_t time,
308  uint64_t sInstId, bool syncEc, std::string &error_message_out)
309 {
310  if (ArmSystem::callSemihosting(this, true)) {
311  // Stop execution in case an exit of the sim loop was scheduled. We
312  // don't want to keep executing instructions in the mean time.
313  call().perInstanceExecution_setState(_instId, false);
314 
315  // Schedule an event to resume execution right after any exit has
316  // had a chance to happen.
319 
320  call().semihosting_return(_instId, readIntReg(0));
321  } else {
322  call().semihosting_notImplemented(_instId);
323  }
324  return iris::E_ok;
325 }
326 
328  gem5::BaseCPU *cpu, int id, System *system, gem5::BaseMMU *mmu,
329  BaseISA *isa, iris::IrisConnectionInterface *iris_if,
330  const std::string &iris_path) :
331  _cpu(cpu), _threadId(id), _system(system), _mmu(mmu), _isa(isa),
332  _irisPath(iris_path), vecRegs(ArmISA::NumVecRegs),
333  vecPredRegs(ArmISA::NumVecPredRegs),
334  comInstEventQueue("instruction-based event queue"),
335  client(iris_if, "client." + iris_path)
336 {
337  iris::InstanceInfo info;
338  auto ret_code = noThrow().instanceRegistry_getInstanceInfoByName(
339  info, "component." + iris_path);
340  if (ret_code == iris::E_ok) {
341  // The iris instance registry already new about this path.
342  _instId = info.instId;
343  } else {
344  // This path doesn't (yet) exist. Set the ID to something invalid.
345  _instId = iris::IRIS_UINT64_MAX;
346  }
347 
348  typedef ThreadContext Self;
349  iris::EventSourceInfo evSrcInfo;
350 
351  client.registerEventCallback<Self, &Self::instanceRegistryChanged>(
352  this, "ec_IRIS_INSTANCE_REGISTRY_CHANGED",
353  "Install the iris instance ID", "Iris::ThreadContext");
354  call().event_getEventSource(iris::IrisInstIdGlobalInstance, evSrcInfo,
355  "IRIS_INSTANCE_REGISTRY_CHANGED");
356  regEventStreamId = iris::IRIS_UINT64_MAX;
357  static const std::vector<std::string> fields =
358  { "EVENT", "INST_ID", "INST_NAME" };
359  call().eventStream_create(iris::IrisInstIdGlobalInstance, regEventStreamId,
360  evSrcInfo.evSrcId, client.getInstId(), &fields);
361 
362  client.registerEventCallback<Self, &Self::phaseInitLeave>(
363  this, "ec_IRIS_SIM_PHASE_INIT_LEAVE",
364  "Initialize register contexts", "Iris::ThreadContext");
365  call().event_getEventSource(iris::IrisInstIdSimulationEngine, evSrcInfo,
366  "IRIS_SIM_PHASE_INIT_LEAVE");
367  initEventStreamId = iris::IRIS_UINT64_MAX;
368  call().eventStream_create(
369  iris::IrisInstIdSimulationEngine, initEventStreamId,
370  evSrcInfo.evSrcId, client.getInstId());
371 
372  client.registerEventCallback<Self, &Self::simulationTimeEvent>(
373  this, "ec_IRIS_SIMULATION_TIME_EVENT",
374  "Handle simulation time stopping for breakpoints or stepping",
375  "Iris::ThreadContext");
376  call().event_getEventSource(iris::IrisInstIdSimulationEngine, evSrcInfo,
377  "IRIS_SIMULATION_TIME_EVENT");
378  timeEventStreamId = iris::IRIS_UINT64_MAX;
379  call().eventStream_create(
380  iris::IrisInstIdSimulationEngine, timeEventStreamId,
381  evSrcInfo.evSrcId, client.getInstId());
382 
383  breakpointEventStreamId = iris::IRIS_UINT64_MAX;
384  semihostingEventStreamId = iris::IRIS_UINT64_MAX;
385 
386  auto enable_lambda = [this]{
387  call().perInstanceExecution_setState(_instId, true);
388  };
390  enable_lambda, "resume after pseudo inst",
391  false, Event::Sim_Exit_Pri + 1);
392 }
393 
395 {
396  call().eventStream_destroy(
397  iris::IrisInstIdSimulationEngine, initEventStreamId);
398  initEventStreamId = iris::IRIS_UINT64_MAX;
399  client.unregisterEventCallback("ec_IRIS_SIM_PHASE_INIT_LEAVE");
400 
401  call().eventStream_destroy(
402  iris::IrisInstIdGlobalInstance, regEventStreamId);
403  regEventStreamId = iris::IRIS_UINT64_MAX;
404  client.unregisterEventCallback("ec_IRIS_INSTANCE_REGISTRY_CHANGED");
405 
406  call().eventStream_destroy(
407  iris::IrisInstIdGlobalInstance, timeEventStreamId);
408  timeEventStreamId = iris::IRIS_UINT64_MAX;
409  client.unregisterEventCallback("ec_IRIS_SIMULATION_TIME_EVENT");
410 
413  delete enableAfterPseudoEvent;
414 }
415 
416 bool
418 {
419  auto it = getOrAllocBp(e->pc());
420  it->second->events->push_back(e);
421 
422  if (_instId != iris::IRIS_UINT64_MAX && !it->second->validIds())
423  installBp(it);
424 
425  return true;
426 }
427 
428 bool
430 {
431  auto it = getOrAllocBp(e->pc());
432  it->second->events->remove(e);
433 
434  if (it->second->empty())
435  delBp(it);
436 
437  return true;
438 }
439 
440 void
442  iris::MemorySpaceId space, Addr addr, void *p, size_t size)
443 {
444  iris::r0master::MemoryReadResult r;
445  auto err = call().memory_read(_instId, r, space, addr, 1, size);
446  panic_if(err != iris::r0master::E_ok, "readMem failed.");
447  std::memcpy(p, r.data.data(), size);
448 }
449 
450 void
452  iris::MemorySpaceId space, Addr addr, const void *p, size_t size)
453 {
454  std::vector<uint64_t> data((size + 7) / 8);
455  std::memcpy(data.data(), p, size);
456  iris::MemoryWriteResult r;
457  auto err = call().memory_write(_instId, r, space, addr, 1, size, data);
458  panic_if(err != iris::r0master::E_ok, "writeMem failed.");
459 }
460 
461 bool
462 ThreadContext::translateAddress(Addr &paddr, iris::MemorySpaceId p_space,
463  Addr vaddr, iris::MemorySpaceId v_space)
464 {
465  iris::MemoryAddressTranslationResult result;
466  auto ret = noThrow().memory_translateAddress(
467  _instId, result, v_space, vaddr, p_space);
468 
469  if (ret != iris::E_ok) {
470  // Check if there was a legal translation between these two spaces.
471  // If so, something else went wrong.
472  for (auto &trans: translations)
473  if (trans.inSpaceId == v_space && trans.outSpaceId == p_space)
474  return false;
475 
476  panic("No legal translation IRIS address translation found.");
477  }
478 
479  if (result.address.empty())
480  return false;
481 
482  if (result.address.size() > 1) {
483  warn("Multiple mappings for address %#x.", vaddr);
484  return false;
485  }
486 
487  paddr = result.address[0];
488  return true;
489 }
490 
491 void
493 {
494  Tick now = getCurrentInstCount();
496  if (count <= now)
497  call().simulationTime_stop(iris::IrisInstIdSimulationEngine);
498  else
500 }
501 
502 void
504 {
507 }
508 
509 Tick
511 {
512  uint64_t count;
513  auto ret = call().step_getStepCounterValue(_instId, count, "instruction");
514  panic_if(ret != iris::E_ok, "Failed to get instruction count.");
515  return count;
516 }
517 
518 void
520 {
521  auto msn = ArmISA::isSecure(this) ?
523  auto id = getMemorySpaceId(msn);
524 
525  auto addr = pkt->getAddr();
526  auto size = pkt->getSize();
527  auto data = pkt->getPtr<uint8_t>();
528 
529  pkt->makeResponse();
530  if (pkt->isRead())
531  readMem(id, addr, data, size);
532  else
533  writeMem(id, addr, data, size);
534 }
535 
536 void
538 {
540 }
541 
542 void
544  const char *data)
545 {
547 }
548 
551 {
552  return _status;
553 }
554 
555 void
557 {
560  if (new_status == Active) {
561  if (_status != Active)
562  call().perInstanceExecution_setState(_instId, true);
563  } else {
564  if (_status == Active)
565  call().perInstanceExecution_setState(_instId, false);
566  }
567  _status = new_status;
568 }
569 
570 const PCStateBase &
572 {
573  ArmISA::CPSR cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
574 
575  pc.thumb(cpsr.t);
576  pc.nextThumb(pc.thumb());
577  pc.jazelle(cpsr.j);
578  pc.nextJazelle(cpsr.j);
579  pc.aarch64(!cpsr.width);
580  pc.nextAArch64(!cpsr.width);
581  pc.illegalExec(false);
582  pc.itstate(ArmISA::itState(cpsr));
583  pc.nextItstate(0);
584 
585  iris::ResourceReadResult result;
586  call().resource_read(_instId, result, pcRscId);
587  Addr addr = result.data.at(0);
588  if (cpsr.width && cpsr.t)
589  addr = addr & ~0x1;
590  pc.set(addr);
591 
592  return pc;
593 }
594 void
596 {
597  Addr pc = val.instAddr();
598 
599  ArmISA::CPSR cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
600  if (cpsr.width && cpsr.t)
601  pc = pc | 0x1;
602 
603  iris::ResourceWriteResult result;
604  call().resource_write(_instId, result, pcRscId, pc);
605 }
606 
607 iris::ResourceId
609 {
610  iris::ResourceId rsc_id = iris::IRIS_UINT64_MAX;
611  if (misc_reg < miscRegIds.size())
612  rsc_id = miscRegIds.at(misc_reg);
613 
614  panic_if(rsc_id == iris::IRIS_UINT64_MAX,
615  "Misc reg %s is not supported by fast model.",
616  ArmISA::miscRegClass[misc_reg]);
617  return rsc_id;
618 }
619 
620 RegVal
622 {
623  iris::ResourceReadResult result;
624  call().resource_read(_instId, result, getMiscRegRscId(misc_reg));
625  return result.data.at(0);
626 }
627 
628 void
630 {
631  iris::ResourceWriteResult result;
632  call().resource_write(_instId, result, getMiscRegRscId(misc_reg), val);
633 }
634 
635 RegVal
637 {
638  RegVal val;
639  getReg(reg, &val);
640  return val;
641 }
642 
643 void
645 {
646  setReg(reg, &val);
647 }
648 
649 void
650 ThreadContext::getReg(const RegId &reg, void *val) const
651 {
652  const RegIndex idx = reg.index();
653  const bool flat = reg.regClass().isFlat();
654  const RegClassType type = reg.classValue();
655  if (flat) {
656  switch (type) {
657  case IntRegClass:
658  *(RegVal *)val = readIntRegFlat(idx);
659  break;
660  case VecRegClass:
662  break;
663  case VecElemClass:
664  *(RegVal *)val = readVecElemFlat(idx);
665  break;
666  case VecPredRegClass:
668  break;
669  case CCRegClass:
670  *(RegVal *)val = readCCRegFlat(idx);
671  break;
672  case MiscRegClass:
673  panic("MiscRegs should not be read with getReg.");
674  default:
675  panic("Unrecognized register class type %d.", type);
676  }
677  } else {
678  switch (type) {
679  case IntRegClass:
680  *(RegVal *)val = readIntReg(idx);
681  break;
682  case VecRegClass:
684  break;
685  case VecElemClass:
686  *(RegVal *)val = readVecElem(reg);
687  break;
688  case VecPredRegClass:
690  break;
691  case CCRegClass:
692  *(RegVal *)val = readCCReg(idx);
693  break;
694  case MiscRegClass:
695  panic("MiscRegs should not be read with getReg.");
696  default:
697  panic("Unrecognized register class type %d.", type);
698  }
699  }
700 }
701 
702 void
703 ThreadContext::setReg(const RegId &reg, const void *val)
704 {
705  const RegIndex idx = reg.index();
706  const bool flat = reg.regClass().isFlat();
707  const RegClassType type = reg.classValue();
708  if (flat) {
709  switch (type) {
710  case IntRegClass:
711  setIntRegFlat(idx, *(RegVal *)val);
712  break;
713  case VecRegClass:
715  break;
716  case VecElemClass:
717  setVecElemFlat(idx, *(RegVal *)val);
718  break;
719  case VecPredRegClass:
721  break;
722  case CCRegClass:
723  setCCRegFlat(idx, *(RegVal *)val);
724  break;
725  case MiscRegClass:
726  panic("MiscRegs should not be read with getReg.");
727  default:
728  panic("Unrecognized register class type %d.", type);
729  }
730  } else {
731  switch (type) {
732  case IntRegClass:
733  setIntReg(idx, *(RegVal *)val);
734  break;
735  case VecRegClass:
737  break;
738  case VecElemClass:
739  setVecElem(reg, *(RegVal *)val);
740  break;
741  case VecPredRegClass:
743  break;
744  case CCRegClass:
745  setCCReg(idx, *(RegVal *)val);
746  break;
747  case MiscRegClass:
748  panic("MiscRegs should not be read with getReg.");
749  default:
750  panic("Unrecognized register class type %d.", type);
751  }
752  }
753 }
754 
755 void *
757 {
758  const RegIndex idx = reg.index();
759  const bool flat = reg.regClass().isFlat();
760  const RegClassType type = reg.classValue();
761  if (flat) {
762  switch (type) {
763  case VecRegClass:
764  return &getWritableVecRegFlat(idx);
765  case VecPredRegClass:
766  return &getWritableVecPredRegFlat(idx);
767  default:
768  panic("Unrecognized register class type %d.", type);
769  }
770  } else {
771  switch (type) {
772  case VecRegClass:
773  return &getWritableVecReg(reg);
774  case VecPredRegClass:
775  return &getWritableVecPredReg(reg);
776  default:
777  panic("Unrecognized register class type %d.", type);
778  }
779  }
780 }
781 
782 iris::ResourceId
784 {
785  ArmISA::CPSR cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
786  auto &regIds = cpsr.width ? intReg32Ids : intReg64Ids;
787  iris::ResourceId rsc_id = iris::IRIS_UINT64_MAX;
788  if (int_reg < regIds.size())
789  rsc_id = regIds.at(int_reg);
790 
791  panic_if(rsc_id == iris::IRIS_UINT64_MAX,
792  "Int reg %s is not supported by fast model.",
793  ArmISA::intRegClass[int_reg]);
794  return rsc_id;
795 }
796 
797 RegVal
799 {
800  iris::ResourceReadResult result;
801  call().resource_read(_instId, result, getIntRegRscId(reg_idx));
802  return result.data.at(0);
803 }
804 
805 void
807 {
808  iris::ResourceWriteResult result;
809  call().resource_write(_instId, result, getIntRegRscId(reg_idx), val);
810 }
811 
812 iris::ResourceId
814 {
815  iris::ResourceId rsc_id = iris::IRIS_UINT64_MAX;
816  if (int_reg < flattenedIntIds.size())
817  rsc_id = flattenedIntIds.at(int_reg);
818  return rsc_id;
819 }
820 
821 /*
822  * The 64 bit version of registers gives us a pre-flattened view of the reg
823  * file, no matter what mode we're in or if we're currently 32 or 64 bit.
824  */
825 RegVal
827 {
828  auto rsc_id = getIntRegFlatRscId(idx);
829  if (rsc_id == iris::IRIS_UINT64_MAX)
830  return 0;
831  iris::ResourceReadResult result;
832  call().resource_read(_instId, result, rsc_id);
833  return result.data.at(0);
834 }
835 
836 void
838 {
839  auto rsc_id = getIntRegFlatRscId(idx);
840  panic_if(rsc_id == iris::IRIS_UINT64_MAX,
841  "Int reg %s is not supported by fast model.",
842  ArmISA::intRegClass[idx]);
843  iris::ResourceWriteResult result;
844  call().resource_write(_instId, result, rsc_id, val);
845 }
846 
847 iris::ResourceId
849 {
850  iris::ResourceId rsc_id = iris::IRIS_UINT64_MAX;
851  if (cc_reg < ccRegIds.size())
852  rsc_id = ccRegIds.at(cc_reg);
853  return rsc_id;
854 }
855 
856 RegVal
858 {
859  auto rsc_id = getCCRegFlatRscId(idx);
860  if (rsc_id == iris::IRIS_UINT64_MAX)
861  return 0;
862  iris::ResourceReadResult result;
863  call().resource_read(_instId, result, rsc_id);
864  return result.data.at(0);
865 }
866 
867 void
869 {
870  auto rsc_id = getCCRegFlatRscId(idx);
871  panic_if(rsc_id == iris::IRIS_UINT64_MAX,
872  "CC reg %s is not supported by fast model.",
873  ArmISA::ccRegClass[idx]);
874  iris::ResourceWriteResult result;
875  call().resource_write(_instId, result, rsc_id, val);
876 }
877 
878 iris::ResourceId
880 {
881  iris::ResourceId rsc_id = iris::IRIS_UINT64_MAX;
882  if (vec_reg < vecRegIds.size())
883  rsc_id = vecRegIds.at(vec_reg);
884  return rsc_id;
885 }
886 
888 ThreadContext::readVecReg(const RegId &reg_id) const
889 {
890  const RegIndex idx = reg_id.index();
892  reg.zero();
893 
894  // Ignore accesses to registers which aren't architected. gem5 defines a
895  // few extra registers which it uses internally in the implementation of
896  // some instructions.
897  auto rsc_id = getVecRegRscId(reg_id);
898  if (rsc_id == iris::IRIS_UINT64_MAX)
899  return reg;
900 
901  iris::ResourceReadResult result;
902  call().resource_read(_instId, result, rsc_id);
903  size_t data_size = result.data.size() * (sizeof(*result.data.data()));
904  size_t size = std::min(data_size, reg.size());
905  memcpy(reg.as<uint8_t>(), (void *)result.data.data(), size);
906 
907  return reg;
908 }
909 
912 {
913  return readVecReg(ArmISA::vecRegClass[idx]);
914 }
915 
916 iris::ResourceId
918 {
919  iris::ResourceId rsc_id = iris::IRIS_UINT64_MAX;
920  if (vec_reg < vecPredRegIds.size())
921  rsc_id = vecPredRegIds.at(vec_reg);
922  return rsc_id;
923 }
924 
927 {
928  RegIndex idx = reg_id.index();
929 
931  reg.reset();
932 
933  auto rsc_id = getVecPredRegRscId(reg_id);
934  if (rsc_id == iris::IRIS_UINT64_MAX)
935  return reg;
936 
937  iris::ResourceReadResult result;
938  call().resource_read(_instId, result, rsc_id);
939 
940  size_t offset = 0;
941  size_t num_bits = reg.NUM_BITS;
942  uint8_t *bytes = (uint8_t *)result.data.data();
943  while (num_bits > 8) {
944  reg.setBits(offset, 8, *bytes);
945  offset += 8;
946  num_bits -= 8;
947  bytes++;
948  }
949  if (num_bits)
950  reg.setBits(offset, num_bits, *bytes);
951 
952  return reg;
953 }
954 
957 {
959 }
960 
961 } // namespace Iris
962 } // namespace gem5
const char data[]
static bool callSemihosting(ThreadContext *tc, bool gem5_ops=false)
Make a Semihosting call from either aarch64 or aarch32.
Definition: system.cc:190
Tick nextTick() const
Definition: eventq.hh:843
virtual void initFromIrisInstance(const ResourceMap &resources)
virtual void setVecPredReg(const RegId &reg, const ArmISA::VecPredRegContainer &val)
void * getWritableReg(const RegId &reg) override
ThreadContext(gem5::BaseCPU *cpu, int id, System *system, gem5::BaseMMU *mmu, gem5::BaseISA *isa, iris::IrisConnectionInterface *iris_if, const std::string &iris_path)
iris::ResourceId getMiscRegRscId(RegIndex misc_reg) const
bool remove(PCEvent *e) override
void uninstallBp(BpInfoIt it)
void setStatus(Status new_status) override
void readMemWithCurrentMsn(Addr vaddr, size_t size, char *data)
virtual RegVal readVecElemFlat(RegIndex idx) const
virtual void setCCReg(RegIndex reg_idx, RegVal val)
virtual void setVecReg(const RegId &reg, const ArmISA::VecRegContainer &val)
std::vector< iris::MemorySupportedAddressTranslationResult > translations
virtual const std::vector< iris::MemorySpaceId > & getBpSpaceIds() const =0
virtual RegVal readCCRegFlat(RegIndex idx) const
iris::IrisCppAdapter & noThrow() const
void installBp(BpInfoIt it)
iris::ResourceId getIntRegFlatRscId(RegIndex int_reg) const
Flat register interfaces.
void descheduleInstCountEvent(Event *event) override
virtual RegVal readCCReg(RegIndex reg_idx) const
virtual ArmISA::VecRegContainer & getWritableVecRegFlat(RegIndex idx)
Status status() const override
void sendFunctional(PacketPtr pkt) override
void extractResourceMap(ResourceIds &ids, const ResourceMap &resources, const IdxNameMap &idx_names)
iris::ResourceId getVecPredRegRscId(RegIndex vec_reg) const
bool translateAddress(Addr &paddr, iris::MemorySpaceId p_space, Addr vaddr, iris::MemorySpaceId v_space)
iris::ResourceId getVecRegRscId(RegIndex vec_reg) const
void writeMem(iris::MemorySpaceId space, Addr addr, const void *p, size_t size)
iris::IrisErrorCode phaseInitLeave(uint64_t esId, const iris::IrisValueMap &fields, uint64_t time, uint64_t sInstId, bool syncEc, std::string &error_message_out)
virtual RegVal readIntRegFlat(RegIndex idx) const
iris::IrisCppAdapter & call() const
Tick getCurrentInstCount() override
const PCStateBase & pcState() const override
virtual const ArmISA::VecPredRegContainer & readVecPredReg(const RegId &reg) const
virtual void setVecPredRegFlat(RegIndex idx, const ArmISA::VecPredRegContainer &val)
iris::IrisErrorCode semihostingEvent(uint64_t esId, const iris::IrisValueMap &fields, uint64_t time, uint64_t sInstId, bool syncEc, std::string &error_message_out)
virtual RegVal readVecElem(const RegId &reg) const
iris::IrisErrorCode simulationTimeEvent(uint64_t esId, const iris::IrisValueMap &fields, uint64_t time, uint64_t sInstId, bool syncEc, std::string &error_message_out)
virtual const ArmISA::VecRegContainer & readVecReg(const RegId &reg) const
iris::ResourceId getCCRegFlatRscId(RegIndex cc_reg) const
RegVal getReg(const RegId &reg) const override
iris::EventStreamId regEventStreamId
virtual void setVecRegFlat(RegIndex idx, const ArmISA::VecRegContainer &val)
iris::EventStreamId initEventStreamId
iris::EventStreamId semihostingEventStreamId
void readMem(iris::MemorySpaceId space, Addr addr, void *p, size_t size)
BpInfoIt getOrAllocBp(Addr pc)
virtual ArmISA::VecPredRegContainer & getWritableVecPredReg(const RegId &reg)
gem5::BaseCPU * getCpuPtr() override
std::vector< ArmISA::VecRegContainer > vecRegs
std::map< std::string, iris::ResourceInfo > ResourceMap
std::map< int, std::string > IdxNameMap
virtual void setVecElemFlat(RegIndex idx, RegVal val)
iris::MemorySpaceId getMemorySpaceId(const Iris::CanonicalMsn &msn) const
virtual ArmISA::VecRegContainer & getWritableVecReg(const RegId &reg)
RegVal readMiscRegNoEffect(RegIndex misc_reg) const override
void suspend() override
Set the status to Suspended.
iris::IrisErrorCode breakpointHit(uint64_t esId, const iris::IrisValueMap &fields, uint64_t time, uint64_t sInstId, bool syncEc, std::string &error_message_out)
iris::InstanceId _instId
std::vector< ArmISA::VecPredRegContainer > vecPredRegs
virtual void setIntRegFlat(RegIndex idx, uint64_t val)
iris::ResourceId pcRscId
virtual ArmISA::VecPredRegContainer readVecPredRegFlat(RegIndex idx) const
BpInfoMap::iterator BpInfoIt
iris::ResourceId extractResourceId(const ResourceMap &resources, const std::string &name)
void writeMemWithCurrentMsn(Addr vaddr, size_t size, const char *data)
virtual RegVal readIntReg(RegIndex reg_idx) const
std::vector< iris::MemorySpaceInfo > memorySpaces
virtual void setVecElem(const RegId &reg, RegVal val)
virtual void setIntReg(RegIndex reg_idx, RegVal val)
iris::EventStreamId timeEventStreamId
bool schedule(PCEvent *e) override
iris::ResourceId getIntRegRscId(RegIndex int_reg) const
iris::EventStreamId breakpointEventStreamId
virtual void setCCRegFlat(RegIndex idx, RegVal val)
void scheduleInstCountEvent(Event *event, Tick count) override
virtual const ArmISA::VecRegContainer & readVecRegFlat(RegIndex idx) const
virtual ArmISA::VecPredRegContainer & getWritableVecPredRegFlat(RegIndex idx)
iris::IrisErrorCode instanceRegistryChanged(uint64_t esId, const iris::IrisValueMap &fields, uint64_t time, uint64_t sInstId, bool syncEc, std::string &error_message_out)
void setReg(const RegId &reg, RegVal val) override
iris::IrisInstance client
void setMiscRegNoEffect(RegIndex misc_reg, const RegVal val) override
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
bool isRead() const
Definition: packet.hh:592
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1212
Addr getAddr() const
Definition: packet.hh:805
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition: packet.hh:1059
unsigned getSize() const
Definition: packet.hh:815
Register ID: describe an architectural register with its class and index.
Definition: reg_class.hh:91
constexpr RegIndex index() const
Index accessors.
Definition: reg_class.hh:148
@ Suspended
Temporarily inactive.
Vector Register Abstraction This generic class is the model in a particularization of MVC,...
Definition: vec_reg.hh:124
void schedule(Event *event, Tick when, bool global=false)
Schedule the given event on this queue.
Definition: eventq.hh:764
void deschedule(Event *event)
Deschedule the specified event.
Definition: eventq.hh:797
void deschedule(Event &event)
Definition: eventq.hh:1028
void serviceEvents(Tick when)
process all events up to the given timestamp.
Definition: eventq.hh:876
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
static const Priority Sim_Exit_Pri
If we want to exit on this cycle, it's the very last thing we do.
Definition: eventq.hh:234
bool empty() const
Returns true if no events are queued.
Definition: eventq.hh:898
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:204
#define warn(...)
Definition: logging.hh:246
Bitfield< 39, 36 > ids
Definition: misc_types.hh:154
constexpr RegClass ccRegClass(CCRegClass, CCRegClassName, cc_reg::NumRegs, debug::CCRegs)
const int NumVecPredRegs
Definition: vec.hh:84
bool isSecure(ThreadContext *tc)
Definition: utility.cc:74
VecPredReg::Container VecPredRegContainer
Definition: vec.hh:71
Bitfield< 6 > err
Definition: misc_types.hh:809
Bitfield< 23, 0 > offset
Definition: types.hh:144
Bitfield< 9 > e
Definition: misc_types.hh:65
Bitfield< 33 > id
Definition: misc_types.hh:257
const int NumVecRegs
Definition: vec.hh:83
constexpr RegClass intRegClass
Definition: int.hh:173
constexpr RegClass vecPredRegClass
Definition: vec.hh:109
@ MISCREG_CPSR
Definition: misc.hh:65
constexpr RegClass miscRegClass
Definition: misc.hh:2726
static uint8_t itState(CPSR psr)
Definition: utility.hh:191
constexpr RegClass vecRegClass
Definition: vec.hh:101
@ PhysicalMemorySecureMsn
@ PhysicalMemoryNonSecureMsn
Bitfield< 4 > pc
Bitfield< 10, 5 > event
Bitfield< 5 > r
Definition: pagetable.hh:60
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 5, 3 > reg
Definition: types.hh:92
Bitfield< 15 > system
Definition: misc.hh:1004
Bitfield< 63 > val
Definition: misc.hh:776
Bitfield< 3 > addr
Definition: types.hh:84
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
uint16_t RegIndex
Definition: types.hh:176
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
uint64_t Tick
Tick count type.
Definition: types.hh:58
uint64_t RegVal
Definition: types.hh:173
RegClassType
Enumerate the classes of registers.
Definition: reg_class.hh:59
@ VecPredRegClass
Definition: reg_class.hh:66
@ CCRegClass
Condition-code register.
Definition: reg_class.hh:67
@ VecRegClass
Vector Register.
Definition: reg_class.hh:63
@ IntRegClass
Integer register.
Definition: reg_class.hh:60
@ MiscRegClass
Control (misc) register.
Definition: reg_class.hh:68
@ VecElemClass
Vector Register Native Elem lane.
Definition: reg_class.hh:65
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:24 for gem5 by doxygen 1.9.1