gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  * Authors: Ali Saidi
29  */
30 
38 #include "dev/sparc/iob.hh"
39 
40 #include <cstring>
41 
42 #include "arch/sparc/faults.hh"
43 #include "arch/sparc/interrupts.hh"
44 #include "arch/sparc/isa_traits.hh"
45 #include "base/bitfield.hh"
46 #include "base/trace.hh"
47 #include "cpu/intr_control.hh"
48 #include "cpu/thread_context.hh"
49 #include "debug/Iob.hh"
50 #include "dev/platform.hh"
51 #include "mem/packet_access.hh"
52 #include "mem/port.hh"
53 #include "sim/faults.hh"
54 #include "sim/system.hh"
55 
56 Iob::Iob(const Params *p)
57  : PioDevice(p), ic(p->platform->intrctrl)
58 {
59  iobManAddr = ULL(0x9800000000);
60  iobManSize = ULL(0x0100000000);
61  iobJBusAddr = ULL(0x9F00000000);
62  iobJBusSize = ULL(0x0100000000);
63  assert (params()->system->threadContexts.size() <= MaxNiagaraProcs);
64 
65  pioDelay = p->pio_latency;
66 
67  for (int x = 0; x < NumDeviceIds; ++x) {
68  intMan[x].cpu = 0;
69  intMan[x].vector = 0;
70  intCtl[x].mask = true;
71  intCtl[x].pend = false;
72  }
73 
74 }
75 
76 Tick
78 {
79 
80  if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
81  readIob(pkt);
82  else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
83  readJBus(pkt);
84  else
85  panic("Invalid address reached Iob\n");
86 
87  pkt->makeAtomicResponse();
88  return pioDelay;
89 }
90 
91 void
93 {
94  Addr accessAddr = pkt->getAddr() - iobManAddr;
95 
96  assert(IntManAddr == 0);
97  if (accessAddr < IntManAddr + IntManSize) {
98  int index = (accessAddr - IntManAddr) >> 3;
99  uint64_t data = intMan[index].cpu << 8 | intMan[index].vector << 0;
100  pkt->setBE(data);
101  return;
102  }
103 
104  if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
105  int index = (accessAddr - IntCtlAddr) >> 3;
106  uint64_t data = intCtl[index].mask ? 1 << 2 : 0 |
107  intCtl[index].pend ? 1 << 0 : 0;
108  pkt->setBE(data);
109  return;
110  }
111 
112  if (accessAddr == JIntVecAddr) {
113  pkt->setBE(jIntVec);
114  return;
115  }
116 
117  panic("Read to unknown IOB offset 0x%x\n", accessAddr);
118 }
119 
120 void
122 {
123  Addr accessAddr = pkt->getAddr() - iobJBusAddr;
124  ContextID cpuid = pkt->req->contextId();
125  int index;
126  uint64_t data;
127 
128 
129 
130 
131  if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) {
132  index = (accessAddr - JIntData0Addr) >> 3;
133  pkt->setBE(jBusData0[index]);
134  return;
135  }
136 
137  if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) {
138  index = (accessAddr - JIntData1Addr) >> 3;
139  pkt->setBE(jBusData1[index]);
140  return;
141  }
142 
143  if (accessAddr == JIntDataA0Addr) {
144  pkt->setBE(jBusData0[cpuid]);
145  return;
146  }
147 
148  if (accessAddr == JIntDataA1Addr) {
149  pkt->setBE(jBusData1[cpuid]);
150  return;
151  }
152 
153  if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
154  index = (accessAddr - JIntBusyAddr) >> 3;
155  data = jIntBusy[index].busy ? 1 << 5 : 0 |
157  pkt->setBE(data);
158  return;
159  }
160  if (accessAddr == JIntABusyAddr) {
161  data = jIntBusy[cpuid].busy ? 1 << 5 : 0 |
163  pkt->setBE(data);
164  return;
165  };
166 
167  panic("Read to unknown JBus offset 0x%x\n", accessAddr);
168 }
169 
170 Tick
172 {
173  if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
174  writeIob(pkt);
175  else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
176  writeJBus(pkt);
177  else
178  panic("Invalid address reached Iob\n");
179 
180 
181  pkt->makeAtomicResponse();
182  return pioDelay;
183 }
184 
185 void
187 {
188  Addr accessAddr = pkt->getAddr() - iobManAddr;
189  int index;
190  uint64_t data;
191 
192  assert(IntManAddr == 0);
193  if (accessAddr < IntManAddr + IntManSize) {
194  index = (accessAddr - IntManAddr) >> 3;
195  data = pkt->getBE<uint64_t>();
196  intMan[index].cpu = bits(data,12,8);
197  intMan[index].vector = bits(data,5,0);
198  DPRINTF(Iob, "Wrote IntMan %d cpu %d, vec %d\n", index,
199  intMan[index].cpu, intMan[index].vector);
200  return;
201  }
202 
203  if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
204  index = (accessAddr - IntCtlAddr) >> 3;
205  data = pkt->getBE<uint64_t>();
206  intCtl[index].mask = bits(data,2,2);
207  if (bits(data,1,1))
208  intCtl[index].pend = false;
209  DPRINTF(Iob, "Wrote IntCtl %d pend %d cleared %d\n", index,
210  intCtl[index].pend, bits(data,2,2));
211  return;
212  }
213 
214  if (accessAddr == JIntVecAddr) {
215  jIntVec = bits(pkt->getBE<uint64_t>(), 5,0);
216  DPRINTF(Iob, "Wrote jIntVec %d\n", jIntVec);
217  return;
218  }
219 
220  if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) {
221  Type type;
222  int cpu_id;
223  int vector;
224  index = (accessAddr - IntManAddr) >> 3;
225  data = pkt->getBE<uint64_t>();
226  type = (Type)bits(data,17,16);
227  cpu_id = bits(data, 12,8);
228  vector = bits(data,5,0);
229  generateIpi(type,cpu_id, vector);
230  return;
231  }
232 
233  panic("Write to unknown IOB offset 0x%x\n", accessAddr);
234 }
235 
236 void
238 {
239  Addr accessAddr = pkt->getAddr() - iobJBusAddr;
240  ContextID cpuid = pkt->req->contextId();
241  int index;
242  uint64_t data;
243 
244  if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
245  index = (accessAddr - JIntBusyAddr) >> 3;
246  data = pkt->getBE<uint64_t>();
247  jIntBusy[index].busy = bits(data,5,5);
248  DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", index,
249  jIntBusy[index].busy);
250  return;
251  }
252  if (accessAddr == JIntABusyAddr) {
253  data = pkt->getBE<uint64_t>();
254  jIntBusy[cpuid].busy = bits(data,5,5);
255  DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", cpuid,
256  jIntBusy[cpuid].busy);
257  return;
258  };
259 
260  panic("Write to unknown JBus offset 0x%x\n", accessAddr);
261 }
262 
263 void
265 {
266  assert(devid < NumDeviceIds);
267  if (intCtl[devid].mask)
268  return;
269  intCtl[devid].mask = true;
270  intCtl[devid].pend = true;
271  DPRINTF(Iob, "Receiving Device interrupt: %d for cpu %d vec %d\n",
272  devid, intMan[devid].cpu, intMan[devid].vector);
273  ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector);
274 }
275 
276 
277 void
278 Iob::generateIpi(Type type, int cpu_id, int vector)
279 {
281  if (cpu_id >= sys->numContexts())
282  return;
283 
284  switch (type) {
285  case 0: // interrupt
286  DPRINTF(Iob, "Generating interrupt because of I/O write to cpu: %d vec %d\n",
287  cpu_id, vector);
288  ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
289  break;
290  case 1: // reset
291  warn("Sending reset to CPU: %d\n", cpu_id);
292  if (vector != por->trapType())
293  panic("Don't know how to set non-POR reset to cpu\n");
294  por->invoke(sys->threadContexts[cpu_id]);
295  sys->threadContexts[cpu_id]->activate();
296  break;
297  case 2: // idle -- this means stop executing and don't wake on interrupts
298  DPRINTF(Iob, "Idling CPU because of I/O write cpu: %d\n", cpu_id);
299  sys->threadContexts[cpu_id]->halt();
300  break;
301  case 3: // resume
302  DPRINTF(Iob, "Resuming CPU because of I/O write cpu: %d\n", cpu_id);
303  sys->threadContexts[cpu_id]->activate();
304  break;
305  default:
306  panic("Invalid type to generate ipi\n");
307  }
308 }
309 
310 bool
311 Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
312 {
313  // If we are already dealing with an interrupt for that cpu we can't deal
314  // with another one right now... come back later
315  if (jIntBusy[cpu_id].busy)
316  return false;
317 
318  DPRINTF(Iob, "Receiving jBus interrupt: %d for cpu %d vec %d\n",
319  source, cpu_id, jIntVec);
320 
321  jIntBusy[cpu_id].busy = true;
322  jIntBusy[cpu_id].source = source;
323  jBusData0[cpu_id] = d0;
324  jBusData1[cpu_id] = d1;
325 
326  ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec);
327  return true;
328 }
329 
332 {
333  AddrRangeList ranges;
334  ranges.push_back(RangeSize(iobManAddr, iobManSize));
335  ranges.push_back(RangeSize(iobJBusAddr, iobJBusSize));
336  return ranges;
337 }
338 
339 
340 void
342 {
343 
347  for (int x = 0; x < NumDeviceIds; x++) {
348  ScopedCheckpointSection sec(cp, csprintf("Int%d", x));
349  paramOut(cp, "cpu", intMan[x].cpu);
350  paramOut(cp, "vector", intMan[x].vector);
351  paramOut(cp, "mask", intCtl[x].mask);
352  paramOut(cp, "pend", intCtl[x].pend);
353  };
354  for (int x = 0; x < MaxNiagaraProcs; x++) {
355  ScopedCheckpointSection sec(cp, csprintf("jIntBusy%d", x));
356  paramOut(cp, "busy", jIntBusy[x].busy);
357  paramOut(cp, "source", jIntBusy[x].source);
358  };
359 }
360 
361 void
363 {
367  for (int x = 0; x < NumDeviceIds; x++) {
368  ScopedCheckpointSection sec(cp, csprintf("Int%d", x));
369  paramIn(cp, "cpu", intMan[x].cpu);
370  paramIn(cp, "vector", intMan[x].vector);
371  paramIn(cp, "mask", intCtl[x].mask);
372  paramIn(cp, "pend", intCtl[x].pend);
373  };
374  for (int x = 0; x < MaxNiagaraProcs; x++) {
375  ScopedCheckpointSection sec(cp, csprintf("jIntBusy%d", x));
376  paramIn(cp, "busy", jIntBusy[x].busy);
377  paramIn(cp, "source", jIntBusy[x].source);
378  };
379 }
380 
381 Iob *
382 IobParams::create()
383 {
384  return new Iob(this);
385 }
Addr iobManAddr
Definition: iob.hh:77
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
#define DPRINTF(x,...)
Definition: trace.hh:229
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:584
This device implements the niagara I/O Bridge chip.
Addr iobManSize
Definition: iob.hh:78
Bitfield< 30, 0 > index
AddrRangeList getAddrRanges() const override
Every PIO device is obliged to provide an implementation that returns the address ranges the device r...
Definition: iob.cc:331
void receiveDeviceInterrupt(DeviceId devid)
Definition: iob.cc:264
bool mask
Definition: iob.hh:97
bool busy
Definition: iob.hh:102
void post(int cpu_id, int int_num, int index)
Definition: intr_control.cc:50
const Addr JIntVecAddr
Definition: iob.hh:50
PioDeviceParams Params
Definition: io_device.hh:134
Bitfield< 28, 21 > cpuid
Definition: dt_constants.hh:94
Definition: cprintf.cc:42
void setBE(T v)
Set the value in the data pointer to v as big endian.
Type
Definition: iob.hh:106
IntMan intMan[NumDeviceIds]
Definition: iob.hh:113
RequestPtr req
A pointer to the original request.
Definition: packet.hh:327
const Addr JIntDataA1Addr
Definition: iob.hh:59
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:645
void generateIpi(Type type, int cpu_id, int vector)
Definition: iob.cc:278
uint8_t type
Definition: inet.hh:333
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:162
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: iob.cc:171
void writeJBus(PacketPtr pkt)
Definition: iob.cc:237
const Addr IntCtlSize
Definition: iob.hh:49
Iob(const Params *p)
Definition: iob.cc:56
uint64_t jIntVec
Definition: iob.hh:115
void makeAtomicResponse()
Definition: packet.hh:949
uint64_t Tick
Tick count type.
Definition: types.hh:63
void writeIob(PacketPtr pkt)
Definition: iob.cc:186
Definition: iob.hh:73
void paramOut(CheckpointOut &cp, const string &name, ExtMachInst const &machInst)
Definition: types.cc:40
Tick pioDelay
Definition: iob.hh:81
std::vector< ThreadContext * > threadContexts
Definition: system.hh:190
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:658
int vector
Definition: iob.hh:93
Addr getAddr() const
Definition: packet.hh:726
unsigned numContexts() const
Definition: system.hh:206
DeviceId
Definition: iob.hh:83
const Addr JIntBusySize
Definition: iob.hh:61
bool receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
Definition: iob.cc:311
uint64_t jBusData0[MaxNiagaraProcs]
Definition: iob.hh:116
Port Object Declaration.
This device is the base class which all devices senstive to an address range inherit from...
Definition: io_device.hh:102
const Addr JIntBusyAddr
Definition: iob.hh:60
const Addr JIntABusyAddr
Definition: iob.hh:62
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
#define ULL(N)
uint64_t constant
Definition: types.hh:50
System * sys
Definition: io_device.hh:105
bool pend
Definition: iob.hh:98
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
Bitfield< 15, 8 > vector
Definition: intmessage.hh:46
void readIob(PacketPtr pkt)
Definition: iob.cc:92
Bitfield< 15 > system
Definition: misc.hh:999
Addr iobJBusAddr
Definition: iob.hh:79
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: iob.cc:341
void readJBus(PacketPtr pkt)
Definition: iob.cc:121
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:643
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:661
const Addr IntVecDisAddr
Definition: iob.hh:51
Generic interface for platforms.
const Addr IntVecDisSize
Definition: iob.hh:52
std::ostream CheckpointOut
Definition: serialize.hh:68
const Addr IntCtlAddr
Definition: iob.hh:48
const Params * params() const
Definition: iob.hh:130
IntBusy jIntBusy[MaxNiagaraProcs]
Definition: iob.hh:118
const Addr JIntData0Addr
Definition: iob.hh:56
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
Definition: types.cc:71
IntrControl * ic
Definition: iob.hh:76
Bitfield< 3, 0 > mask
Definition: types.hh:64
int cpu
Definition: iob.hh:92
#define warn(...)
Definition: logging.hh:212
const int MaxNiagaraProcs
Definition: iob.hh:44
Addr iobJBusSize
Definition: iob.hh:80
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:72
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: iob.cc:77
const Addr JIntDataA0Addr
Definition: iob.hh:58
uint64_t jBusData1[MaxNiagaraProcs]
Definition: iob.hh:117
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr)
Definition: faults.cc:500
Scoped checkpoint section helper class.
Definition: serialize.hh:173
Bitfield< 0 > p
Bitfield< 1 > x
Definition: types.hh:105
IntCtl intCtl[NumDeviceIds]
Definition: iob.hh:114
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: iob.cc:362
const char data[]
int source
Definition: iob.hh:103
int ContextID
Globally unique thread context ID.
Definition: types.hh:231
const Addr JIntData1Addr
Definition: iob.hh:57
bool ic(TxDesc *d)
T getBE() const
Get the data in the packet byte swapped from big endian to host endian.
TrapType trapType()
Definition: faults.hh:89
const Addr IntManAddr
Definition: iob.hh:46
const Addr IntManSize
Definition: iob.hh:47

Generated on Fri Feb 28 2020 16:27:01 for gem5 by doxygen 1.8.13