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

Generated on Wed Sep 30 2020 14:02:11 for gem5 by doxygen 1.8.17