gem5  v22.1.0.0
iob.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006 The Regents of The University of Michigan
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
36 #include "dev/sparc/iob.hh"
37 
38 #include <cstring>
39 
40 #include "arch/sparc/faults.hh"
41 #include "arch/sparc/interrupts.hh"
42 #include "base/bitfield.hh"
43 #include "base/trace.hh"
44 #include "cpu/base.hh"
45 #include "cpu/thread_context.hh"
46 #include "debug/Iob.hh"
47 #include "dev/platform.hh"
48 #include "mem/packet_access.hh"
49 #include "mem/port.hh"
50 #include "sim/faults.hh"
51 #include "sim/system.hh"
52 
53 namespace gem5
54 {
55 
57 {
58  iobManAddr = 0x9800000000ULL;
59  iobManSize = 0x0100000000ULL;
60  iobJBusAddr = 0x9F00000000ULL;
61  iobJBusSize = 0x0100000000ULL;
62  assert(params().system->threads.size() <= MaxNiagaraProcs);
63 
64  pioDelay = p.pio_latency;
65 
66  for (int x = 0; x < NumDeviceIds; ++x) {
67  intMan[x].cpu = 0;
68  intMan[x].vector = 0;
69  intCtl[x].mask = true;
70  intCtl[x].pend = false;
71  }
72 
73 }
74 
75 Tick
77 {
78 
79  if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
80  readIob(pkt);
81  else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
82  readJBus(pkt);
83  else
84  panic("Invalid address reached Iob\n");
85 
86  pkt->makeAtomicResponse();
87  return pioDelay;
88 }
89 
90 void
92 {
93  Addr accessAddr = pkt->getAddr() - iobManAddr;
94 
95  assert(IntManAddr == 0);
96  if (accessAddr < IntManAddr + IntManSize) {
97  int index = (accessAddr - IntManAddr) >> 3;
98  uint64_t data = intMan[index].cpu << 8 | intMan[index].vector << 0;
99  pkt->setBE(data);
100  return;
101  }
102 
103  if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
104  int index = (accessAddr - IntCtlAddr) >> 3;
105  uint64_t data = (intCtl[index].mask ? (1 << 2) : 0) |
106  (intCtl[index].pend ? (1 << 0) : 0);
107  pkt->setBE(data);
108  return;
109  }
110 
111  if (accessAddr == JIntVecAddr) {
112  pkt->setBE(jIntVec);
113  return;
114  }
115 
116  panic("Read to unknown IOB offset 0x%x\n", accessAddr);
117 }
118 
119 void
121 {
122  Addr accessAddr = pkt->getAddr() - iobJBusAddr;
123  ContextID cpuid = pkt->req->contextId();
124  int index;
125  uint64_t data;
126 
127 
128 
129 
130  if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) {
131  index = (accessAddr - JIntData0Addr) >> 3;
132  pkt->setBE(jBusData0[index]);
133  return;
134  }
135 
136  if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) {
137  index = (accessAddr - JIntData1Addr) >> 3;
138  pkt->setBE(jBusData1[index]);
139  return;
140  }
141 
142  if (accessAddr == JIntDataA0Addr) {
143  pkt->setBE(jBusData0[cpuid]);
144  return;
145  }
146 
147  if (accessAddr == JIntDataA1Addr) {
148  pkt->setBE(jBusData1[cpuid]);
149  return;
150  }
151 
152  if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
153  index = (accessAddr - JIntBusyAddr) >> 3;
154  data = jIntBusy[index].busy ? 1 << 5 : 0 |
156  pkt->setBE(data);
157  return;
158  }
159  if (accessAddr == JIntABusyAddr) {
160  data = jIntBusy[cpuid].busy ? 1 << 5 : 0 |
162  pkt->setBE(data);
163  return;
164  };
165 
166  panic("Read to unknown JBus offset 0x%x\n", accessAddr);
167 }
168 
169 Tick
171 {
172  if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
173  writeIob(pkt);
174  else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
175  writeJBus(pkt);
176  else
177  panic("Invalid address reached Iob\n");
178 
179 
180  pkt->makeAtomicResponse();
181  return pioDelay;
182 }
183 
184 void
186 {
187  Addr accessAddr = pkt->getAddr() - iobManAddr;
188  int index;
189  uint64_t data;
190 
191  assert(IntManAddr == 0);
192  if (accessAddr < IntManAddr + IntManSize) {
193  index = (accessAddr - IntManAddr) >> 3;
194  data = pkt->getBE<uint64_t>();
195  intMan[index].cpu = bits(data,12,8);
196  intMan[index].vector = bits(data,5,0);
197  DPRINTF(Iob, "Wrote IntMan %d cpu %d, vec %d\n", index,
198  intMan[index].cpu, intMan[index].vector);
199  return;
200  }
201 
202  if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
203  index = (accessAddr - IntCtlAddr) >> 3;
204  data = pkt->getBE<uint64_t>();
205  intCtl[index].mask = bits(data,2,2);
206  if (bits(data,1,1))
207  intCtl[index].pend = false;
208  DPRINTF(Iob, "Wrote IntCtl %d pend %d cleared %d\n", index,
209  intCtl[index].pend, bits(data,2,2));
210  return;
211  }
212 
213  if (accessAddr == JIntVecAddr) {
214  jIntVec = bits(pkt->getBE<uint64_t>(), 5,0);
215  DPRINTF(Iob, "Wrote jIntVec %d\n", jIntVec);
216  return;
217  }
218 
219  if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) {
220  Type type;
221  int cpu_id;
222  int vector;
223  index = (accessAddr - IntManAddr) >> 3;
224  data = pkt->getBE<uint64_t>();
225  type = (Type)bits(data,17,16);
226  cpu_id = bits(data, 12,8);
227  vector = bits(data,5,0);
228  generateIpi(type,cpu_id, vector);
229  return;
230  }
231 
232  panic("Write to unknown IOB offset 0x%x\n", accessAddr);
233 }
234 
235 void
237 {
238  Addr accessAddr = pkt->getAddr() - iobJBusAddr;
239  ContextID cpuid = pkt->req->contextId();
240  int index;
241  uint64_t data;
242 
243  if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
244  index = (accessAddr - JIntBusyAddr) >> 3;
245  data = pkt->getBE<uint64_t>();
246  jIntBusy[index].busy = bits(data,5,5);
247  DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", index,
248  jIntBusy[index].busy);
249  return;
250  }
251  if (accessAddr == JIntABusyAddr) {
252  data = pkt->getBE<uint64_t>();
253  jIntBusy[cpuid].busy = bits(data,5,5);
254  DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", cpuid,
255  jIntBusy[cpuid].busy);
256  return;
257  };
258 
259  panic("Write to unknown JBus offset 0x%x\n", accessAddr);
260 }
261 
262 void
264 {
265  assert(devid < NumDeviceIds);
266  if (intCtl[devid].mask)
267  return;
268  intCtl[devid].mask = true;
269  intCtl[devid].pend = true;
270  DPRINTF(Iob, "Receiving Device interrupt: %d for cpu %d vec %d\n",
271  devid, intMan[devid].cpu, intMan[devid].vector);
272  auto tc = sys->threads[intMan[devid].cpu];
273  tc->getCpuPtr()->postInterrupt(tc->threadId(), SparcISA::IT_INT_VEC,
274  intMan[devid].vector);
275 }
276 
277 
278 void
279 Iob::generateIpi(Type type, int cpu_id, int vector)
280 {
283  if (cpu_id >= sys->threads.size())
284  return;
285 
286  auto tc = sys->threads[cpu_id];
287  switch (type) {
288  case 0: // interrupt
289  DPRINTF(Iob,
290  "Generating interrupt because of I/O write to cpu: "
291  "%d vec %d\n",
292  cpu_id, vector);
293  tc->getCpuPtr()->postInterrupt(
294  tc->threadId(), SparcISA::IT_INT_VEC, vector);
295  break;
296  case 1: // reset
297  warn("Sending reset to CPU: %d\n", cpu_id);
298  if (vector != por->trapType())
299  panic("Don't know how to set non-POR reset to cpu\n");
300  por->invoke(tc);
301  tc->activate();
302  break;
303  case 2: // idle -- this means stop executing and don't wake on interrupts
304  DPRINTF(Iob, "Idling CPU because of I/O write cpu: %d\n", cpu_id);
305  tc->halt();
306  break;
307  case 3: // resume
308  DPRINTF(Iob, "Resuming CPU because of I/O write cpu: %d\n", cpu_id);
309  tc->activate();
310  break;
311  default:
312  panic("Invalid type to generate ipi\n");
313  }
314 }
315 
316 bool
317 Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
318 {
319  // If we are already dealing with an interrupt for that cpu we can't deal
320  // with another one right now... come back later
321  if (jIntBusy[cpu_id].busy)
322  return false;
323 
324  DPRINTF(Iob, "Receiving jBus interrupt: %d for cpu %d vec %d\n",
325  source, cpu_id, jIntVec);
326 
327  jIntBusy[cpu_id].busy = true;
328  jIntBusy[cpu_id].source = source;
329  jBusData0[cpu_id] = d0;
330  jBusData1[cpu_id] = d1;
331 
332  auto tc = sys->threads[cpu_id];
333  tc->getCpuPtr()->postInterrupt(
334  tc->threadId(), SparcISA::IT_INT_VEC, jIntVec);
335  return true;
336 }
337 
340 {
341  AddrRangeList ranges;
342  ranges.push_back(RangeSize(iobManAddr, iobManSize));
343  ranges.push_back(RangeSize(iobJBusAddr, iobJBusSize));
344  return ranges;
345 }
346 
347 
348 void
350 {
351 
355  for (int x = 0; x < NumDeviceIds; x++) {
356  ScopedCheckpointSection sec(cp, csprintf("Int%d", x));
357  paramOut(cp, "cpu", intMan[x].cpu);
358  paramOut(cp, "vector", intMan[x].vector);
359  paramOut(cp, "mask", intCtl[x].mask);
360  paramOut(cp, "pend", intCtl[x].pend);
361  };
362  for (int x = 0; x < MaxNiagaraProcs; x++) {
363  ScopedCheckpointSection sec(cp, csprintf("jIntBusy%d", x));
364  paramOut(cp, "busy", jIntBusy[x].busy);
365  paramOut(cp, "source", jIntBusy[x].source);
366  };
367 }
368 
369 void
371 {
375  for (int x = 0; x < NumDeviceIds; x++) {
376  ScopedCheckpointSection sec(cp, csprintf("Int%d", x));
377  paramIn(cp, "cpu", intMan[x].cpu);
378  paramIn(cp, "vector", intMan[x].vector);
379  paramIn(cp, "mask", intCtl[x].mask);
380  paramIn(cp, "pend", intCtl[x].pend);
381  };
382  for (int x = 0; x < MaxNiagaraProcs; x++) {
383  ScopedCheckpointSection sec(cp, csprintf("jIntBusy%d", x));
384  paramIn(cp, "busy", jIntBusy[x].busy);
385  paramIn(cp, "source", jIntBusy[x].source);
386  };
387 }
388 
389 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
Definition: iob.hh:73
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: iob.cc:370
IntCtl intCtl[NumDeviceIds]
Definition: iob.hh:117
AddrRangeList getAddrRanges() const override
Every PIO device is obliged to provide an implementation that returns the address ranges the device r...
Definition: iob.cc:339
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: iob.cc:76
Addr iobJBusAddr
Definition: iob.hh:77
bool receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
Definition: iob.cc:317
void readJBus(PacketPtr pkt)
Definition: iob.cc:120
uint64_t jBusData1[MaxNiagaraProcs]
Definition: iob.hh:120
Iob(const Params &p)
Definition: iob.cc:56
void writeIob(PacketPtr pkt)
Definition: iob.cc:185
IntMan intMan[NumDeviceIds]
Definition: iob.hh:116
Addr iobJBusSize
Definition: iob.hh:78
Addr iobManAddr
Definition: iob.hh:75
void readIob(PacketPtr pkt)
Definition: iob.cc:91
Tick pioDelay
Definition: iob.hh:79
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: iob.cc:349
IntBusy jIntBusy[MaxNiagaraProcs]
Definition: iob.hh:121
Addr iobManSize
Definition: iob.hh:76
DeviceId
Definition: iob.hh:82
@ NumDeviceIds
Definition: iob.hh:87
uint64_t jBusData0[MaxNiagaraProcs]
Definition: iob.hh:119
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: iob.cc:170
void generateIpi(Type type, int cpu_id, int vector)
Definition: iob.cc:279
uint64_t jIntVec
Definition: iob.hh:118
void receiveDeviceInterrupt(DeviceId devid)
Definition: iob.cc:263
void writeJBus(PacketPtr pkt)
Definition: iob.cc:236
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
Addr getAddr() const
Definition: packet.hh:805
void setBE(T v)
Set the value in the data pointer to v as big endian.
T getBE() const
Get the data in the packet byte swapped from big endian to host endian.
RequestPtr req
A pointer to the original request.
Definition: packet.hh:376
void makeAtomicResponse()
Definition: packet.hh:1071
This device is the base class which all devices senstive to an address range inherit from.
Definition: io_device.hh:103
PioDeviceParams Params
Definition: io_device.hh:134
System * sys
Definition: io_device.hh:105
void invoke(ThreadContext *tc, const StaticInstPtr &inst=nullStaticInstPtr)
Definition: faults.cc:500
int size() const
Definition: system.hh:213
Threads threads
Definition: system.hh:313
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:815
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
constexpr uint64_t mask(unsigned nbits)
Generate a 64-bit mask of 'nbits' 1s, right justified.
Definition: bitfield.hh:63
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:618
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:610
const Params & params() const
Definition: sim_object.hh:176
This device implements the niagara I/O Bridge chip.
#define warn(...)
Definition: logging.hh:246
Port Object Declaration.
Bitfield< 30, 0 > index
Bitfield< 28, 21 > cpuid
Definition: dt_constants.hh:95
Bitfield< 20, 16 > d1
Definition: types.hh:66
Bitfield< 15, 6 > d0
Definition: types.hh:65
Bitfield< 4 > x
Definition: pagetable.hh:61
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 15 > system
Definition: misc.hh:1004
Bitfield< 15, 8 > vector
Definition: intmessage.hh:48
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
const Addr IntVecDisSize
Definition: iob.hh:51
const Addr JIntDataA1Addr
Definition: iob.hh:58
const Addr IntManSize
Definition: iob.hh:46
const Addr JIntBusyAddr
Definition: iob.hh:59
const Addr JIntData1Addr
Definition: iob.hh:56
std::ostream CheckpointOut
Definition: serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition: types.cc:40
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition: types.cc:72
const Addr IntCtlSize
Definition: iob.hh:48
const Addr IntCtlAddr
Definition: iob.hh:47
uint64_t Tick
Tick count type.
Definition: types.hh:58
const Addr JIntVecAddr
Definition: iob.hh:49
const Addr JIntABusyAddr
Definition: iob.hh:61
int ContextID
Globally unique thread context ID.
Definition: types.hh:239
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
const Addr JIntData0Addr
Definition: iob.hh:55
const int MaxNiagaraProcs
Definition: iob.hh:43
const Addr IntVecDisAddr
Definition: iob.hh:50
const Addr JIntBusySize
Definition: iob.hh:60
const Addr IntManAddr
Definition: iob.hh:45
const Addr JIntDataA0Addr
Definition: iob.hh:57
Generic interface for platforms.
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568

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