gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
tsunami_cchip.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004-2005 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  * Ron Dreslinski
30  */
31 
37 
38 #include <deque>
39 #include <string>
40 #include <vector>
41 
42 #include "arch/alpha/ev5.hh"
43 #include "base/trace.hh"
44 #include "cpu/intr_control.hh"
45 #include "cpu/thread_context.hh"
46 #include "debug/IPI.hh"
47 #include "debug/Tsunami.hh"
48 #include "dev/alpha/tsunami.hh"
49 #include "dev/alpha/tsunamireg.h"
50 #include "mem/packet.hh"
51 #include "mem/packet_access.hh"
52 #include "mem/port.hh"
53 #include "params/TsunamiCChip.hh"
54 #include "sim/system.hh"
55 
57  : BasicPioDevice(p, 0x10000000), tsunami(p->tsunami)
58 {
59  drir = 0;
60  ipint = 0;
61  itint = 0;
62 
63  for (int x = 0; x < Tsunami::Max_CPUs; x++)
64  {
65  dim[x] = 0;
66  dir[x] = 0;
67  }
68 
69  //Put back pointer in tsunami
70  tsunami->cchip = this;
71 }
72 
73 Tick
75 {
76  DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
77 
78  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
79 
80  Addr regnum = (pkt->getAddr() - pioAddr) >> 6;
81  Addr daddr = (pkt->getAddr() - pioAddr);
82 
83  switch (pkt->getSize()) {
84 
85  case sizeof(uint64_t):
86  pkt->setLE<uint64_t>(0);
87 
88  if (daddr & TSDEV_CC_BDIMS)
89  {
90  pkt->setLE(dim[(daddr >> 4) & 0x3F]);
91  break;
92  }
93 
94  if (daddr & TSDEV_CC_BDIRS)
95  {
96  pkt->setLE(dir[(daddr >> 4) & 0x3F]);
97  break;
98  }
99 
100  switch(regnum) {
101  case TSDEV_CC_CSR:
102  pkt->setLE(0x0);
103  break;
104  case TSDEV_CC_MTR:
105  panic("TSDEV_CC_MTR not implemeted\n");
106  break;
107  case TSDEV_CC_MISC:
108  pkt->setLE(((ipint << 8) & 0xF) | ((itint << 4) & 0xF) |
109  (pkt->req->contextId() & 0x3));
110  // currently, FS cannot handle MT so contextId and
111  // cpuId are effectively the same, don't know if it will
112  // matter if FS becomes MT enabled. I suspect no because
113  // we are currently able to boot up to 64 procs anyway
114  // which would render the CPUID of this register useless
115  // anyway
116  break;
117  case TSDEV_CC_AAR0:
118  case TSDEV_CC_AAR1:
119  case TSDEV_CC_AAR2:
120  case TSDEV_CC_AAR3:
121  pkt->setLE(0);
122  break;
123  case TSDEV_CC_DIM0:
124  pkt->setLE(dim[0]);
125  break;
126  case TSDEV_CC_DIM1:
127  pkt->setLE(dim[1]);
128  break;
129  case TSDEV_CC_DIM2:
130  pkt->setLE(dim[2]);
131  break;
132  case TSDEV_CC_DIM3:
133  pkt->setLE(dim[3]);
134  break;
135  case TSDEV_CC_DIR0:
136  pkt->setLE(dir[0]);
137  break;
138  case TSDEV_CC_DIR1:
139  pkt->setLE(dir[1]);
140  break;
141  case TSDEV_CC_DIR2:
142  pkt->setLE(dir[2]);
143  break;
144  case TSDEV_CC_DIR3:
145  pkt->setLE(dir[3]);
146  break;
147  case TSDEV_CC_DRIR:
148  pkt->setLE(drir);
149  break;
150  case TSDEV_CC_PRBEN:
151  panic("TSDEV_CC_PRBEN not implemented\n");
152  break;
153  case TSDEV_CC_IIC0:
154  case TSDEV_CC_IIC1:
155  case TSDEV_CC_IIC2:
156  case TSDEV_CC_IIC3:
157  panic("TSDEV_CC_IICx not implemented\n");
158  break;
159  case TSDEV_CC_MPR0:
160  case TSDEV_CC_MPR1:
161  case TSDEV_CC_MPR2:
162  case TSDEV_CC_MPR3:
163  panic("TSDEV_CC_MPRx not implemented\n");
164  break;
165  case TSDEV_CC_IPIR:
166  pkt->setLE(ipint);
167  break;
168  case TSDEV_CC_ITIR:
169  pkt->setLE(itint);
170  break;
171  default:
172  panic("default in cchip read reached, accessing 0x%x\n");
173  } // uint64_t
174 
175  break;
176  case sizeof(uint32_t):
177  case sizeof(uint16_t):
178  case sizeof(uint8_t):
179  default:
180  panic("invalid access size(?) for tsunami register!\n");
181  }
182  DPRINTF(Tsunami, "Tsunami CChip: read regnum=%#x size=%d data=%lld\n",
183  regnum, pkt->getSize(), pkt->getLE<uint64_t>());
184 
185  pkt->makeAtomicResponse();
186  return pioDelay;
187 }
188 
189 Tick
191 {
192  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
193  Addr daddr = pkt->getAddr() - pioAddr;
194  Addr regnum = (pkt->getAddr() - pioAddr) >> 6 ;
195 
196 
197  assert(pkt->getSize() == sizeof(uint64_t));
198 
199  DPRINTF(Tsunami, "write - addr=%#x value=%#x\n",
200  pkt->getAddr(), pkt->getLE<uint64_t>());
201 
202  bool supportedWrite = false;
203 
204 
205  if (daddr & TSDEV_CC_BDIMS)
206  {
207  int number = (daddr >> 4) & 0x3F;
208 
209  uint64_t bitvector;
210  uint64_t olddim;
211  uint64_t olddir;
212 
213  olddim = dim[number];
214  olddir = dir[number];
215  dim[number] = pkt->getLE<uint64_t>();
216  dir[number] = dim[number] & drir;
217  for (int x = 0; x < Tsunami::Max_CPUs; x++)
218  {
219  bitvector = ULL(1) << x;
220  // Figure out which bits have changed
221  if ((dim[number] & bitvector) != (olddim & bitvector))
222  {
223  // The bit is now set and it wasn't before (set)
224  if ((dim[number] & bitvector) && (dir[number] & bitvector))
225  {
227  number, AlphaISA::INTLEVEL_IRQ1, x);
228  DPRINTF(Tsunami, "dim write resulting in posting dir"
229  " interrupt to cpu %d\n", number);
230  }
231  else if ((olddir & bitvector) &&
232  !(dir[number] & bitvector))
233  {
234  // The bit was set and now its now clear and
235  // we were interrupting on that bit before
237  number, AlphaISA::INTLEVEL_IRQ1, x);
238  DPRINTF(Tsunami, "dim write resulting in clear"
239  " dir interrupt to cpu %d\n", number);
240 
241  }
242 
243 
244  }
245  }
246  } else {
247  switch(regnum) {
248  case TSDEV_CC_CSR:
249  panic("TSDEV_CC_CSR write\n");
250  case TSDEV_CC_MTR:
251  panic("TSDEV_CC_MTR write not implemented\n");
252  case TSDEV_CC_MISC:
253  uint64_t ipreq;
254  ipreq = (pkt->getLE<uint64_t>() >> 12) & 0xF;
255  //If it is bit 12-15, this is an IPI post
256  if (ipreq) {
257  reqIPI(ipreq);
258  supportedWrite = true;
259  }
260 
261  //If it is bit 8-11, this is an IPI clear
262  uint64_t ipintr;
263  ipintr = (pkt->getLE<uint64_t>() >> 8) & 0xF;
264  if (ipintr) {
265  clearIPI(ipintr);
266  supportedWrite = true;
267  }
268 
269  //If it is the 4-7th bit, clear the RTC interrupt
270  uint64_t itintr;
271  itintr = (pkt->getLE<uint64_t>() >> 4) & 0xF;
272  if (itintr) {
273  clearITI(itintr);
274  supportedWrite = true;
275  }
276 
277  // ignore NXMs
278  if (pkt->getLE<uint64_t>() & 0x10000000)
279  supportedWrite = true;
280 
281  if (!supportedWrite)
282  panic("TSDEV_CC_MISC write not implemented\n");
283 
284  break;
285  case TSDEV_CC_AAR0:
286  case TSDEV_CC_AAR1:
287  case TSDEV_CC_AAR2:
288  case TSDEV_CC_AAR3:
289  panic("TSDEV_CC_AARx write not implemeted\n");
290  case TSDEV_CC_DIM0:
291  case TSDEV_CC_DIM1:
292  case TSDEV_CC_DIM2:
293  case TSDEV_CC_DIM3:
294  int number;
295  if (regnum == TSDEV_CC_DIM0)
296  number = 0;
297  else if (regnum == TSDEV_CC_DIM1)
298  number = 1;
299  else if (regnum == TSDEV_CC_DIM2)
300  number = 2;
301  else
302  number = 3;
303 
304  uint64_t bitvector;
305  uint64_t olddim;
306  uint64_t olddir;
307 
308  olddim = dim[number];
309  olddir = dir[number];
310  dim[number] = pkt->getLE<uint64_t>();
311  dir[number] = dim[number] & drir;
312  for (int x = 0; x < 64; x++) {
313  bitvector = ULL(1) << x;
314  // Figure out which bits have changed
315  if ((dim[number] & bitvector) != (olddim & bitvector)) {
316  // The bit is now set and it wasn't before (set)
317  if ((dim[number] & bitvector) &&
318  (dir[number] & bitvector)) {
320  number, AlphaISA::INTLEVEL_IRQ1, x);
322  "posting dir interrupt to cpu 0\n");
323  } else if ((olddir & bitvector) &&
324  !(dir[number] & bitvector)) {
325  // The bit was set and now its now clear and
326  // we were interrupting on that bit before
328  number, AlphaISA::INTLEVEL_IRQ1, x);
329  DPRINTF(Tsunami, "dim write resulting in clear"
330  " dir interrupt to cpu %d\n", x);
331 
332  }
333 
334 
335  }
336  }
337  break;
338  case TSDEV_CC_DIR0:
339  case TSDEV_CC_DIR1:
340  case TSDEV_CC_DIR2:
341  case TSDEV_CC_DIR3:
342  panic("TSDEV_CC_DIR write not implemented\n");
343  case TSDEV_CC_DRIR:
344  panic("TSDEV_CC_DRIR write not implemented\n");
345  case TSDEV_CC_PRBEN:
346  panic("TSDEV_CC_PRBEN write not implemented\n");
347  case TSDEV_CC_IIC0:
348  case TSDEV_CC_IIC1:
349  case TSDEV_CC_IIC2:
350  case TSDEV_CC_IIC3:
351  panic("TSDEV_CC_IICx write not implemented\n");
352  case TSDEV_CC_MPR0:
353  case TSDEV_CC_MPR1:
354  case TSDEV_CC_MPR2:
355  case TSDEV_CC_MPR3:
356  panic("TSDEV_CC_MPRx write not implemented\n");
357  case TSDEV_CC_IPIR:
358  clearIPI(pkt->getLE<uint64_t>());
359  break;
360  case TSDEV_CC_ITIR:
361  clearITI(pkt->getLE<uint64_t>());
362  break;
363  case TSDEV_CC_IPIQ:
364  reqIPI(pkt->getLE<uint64_t>());
365  break;
366  default:
367  panic("default in cchip read reached, accessing 0x%x\n");
368  } // swtich(regnum)
369  } // not BIG_TSUNAMI write
370  pkt->makeAtomicResponse();
371  return pioDelay;
372 }
373 
374 void
375 TsunamiCChip::clearIPI(uint64_t ipintr)
376 {
377  int numcpus = sys->threadContexts.size();
378  assert(numcpus <= Tsunami::Max_CPUs);
379 
380  if (ipintr) {
381  for (int cpunum=0; cpunum < numcpus; cpunum++) {
382  // Check each cpu bit
383  uint64_t cpumask = ULL(1) << cpunum;
384  if (ipintr & cpumask) {
385  // Check if there is a pending ipi
386  if (ipint & cpumask) {
387  ipint &= ~cpumask;
389  cpunum, AlphaISA::INTLEVEL_IRQ3, 0);
390  DPRINTF(IPI, "clear IPI IPI cpu=%d\n", cpunum);
391  } else {
392  warn("clear IPI for CPU=%d, but NO IPI\n", cpunum);
393  }
394  }
395  }
396  }
397  else
398  panic("Big IPI Clear, but not processors indicated\n");
399 }
400 
401 void
402 TsunamiCChip::clearITI(uint64_t itintr)
403 {
404  int numcpus = sys->threadContexts.size();
405  assert(numcpus <= Tsunami::Max_CPUs);
406 
407  if (itintr) {
408  for (int i=0; i < numcpus; i++) {
409  uint64_t cpumask = ULL(1) << i;
410  if (itintr & cpumask & itint) {
412  itint &= ~cpumask;
413  DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
414  }
415  }
416  } else {
417  panic("Big ITI Clear, but not processors indicated\n");
418  }
419 }
420 
421 void
422 TsunamiCChip::reqIPI(uint64_t ipreq)
423 {
424  int numcpus = sys->threadContexts.size();
425  assert(numcpus <= Tsunami::Max_CPUs);
426 
427  if (ipreq) {
428  for (int cpunum=0; cpunum < numcpus; cpunum++) {
429  // Check each cpu bit
430  uint64_t cpumask = ULL(1) << cpunum;
431  if (ipreq & cpumask) {
432  // Check if there is already an ipi (bits 8:11)
433  if (!(ipint & cpumask)) {
434  ipint |= cpumask;
436  cpunum, AlphaISA::INTLEVEL_IRQ3, 0);
437  DPRINTF(IPI, "send IPI cpu=%d\n", cpunum);
438  } else {
439  warn("post IPI for CPU=%d, but IPI already\n", cpunum);
440  }
441  }
442  }
443  } else {
444  panic("Big IPI Request, but not processors indicated\n");
445  }
446 }
447 
448 
449 void
451 {
452  int size = sys->threadContexts.size();
453  assert(size <= Tsunami::Max_CPUs);
454 
455  for (int i = 0; i < size; i++) {
456  uint64_t cpumask = ULL(1) << i;
457  if (!(cpumask & itint)) {
458  itint |= cpumask;
460  DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d\n", i);
461  }
462  }
463 }
464 
465 void
466 TsunamiCChip::postDRIR(uint32_t interrupt)
467 {
468  uint64_t bitvector = ULL(1) << interrupt;
469  uint64_t size = sys->threadContexts.size();
470  assert(size <= Tsunami::Max_CPUs);
471  drir |= bitvector;
472 
473  for (int i=0; i < size; i++) {
474  dir[i] = dim[i] & drir;
475  if (dim[i] & bitvector) {
477  DPRINTF(Tsunami, "posting dir interrupt to cpu %d,"
478  "interrupt %d\n",i, interrupt);
479  }
480  }
481 }
482 
483 void
484 TsunamiCChip::clearDRIR(uint32_t interrupt)
485 {
486  uint64_t bitvector = ULL(1) << interrupt;
487  uint64_t size = sys->threadContexts.size();
488  assert(size <= Tsunami::Max_CPUs);
489 
490  if (drir & bitvector)
491  {
492  drir &= ~bitvector;
493  for (int i=0; i < size; i++) {
494  if (dir[i] & bitvector) {
496  DPRINTF(Tsunami, "clearing dir interrupt to cpu %d,"
497  "interrupt %d\n",i, interrupt);
498 
499  }
500  dir[i] = dim[i] & drir;
501  }
502  } else {
503  DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt);
504  }
505 }
506 
507 
508 void
510 {
516 }
517 
518 void
520 {
526 }
527 
528 TsunamiCChip *
529 TsunamiCChipParams::create()
530 {
531  return new TsunamiCChip(this);
532 }
IntrControl * intrctrl
Pointer to the interrupt controller.
Definition: platform.hh:56
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
#define DPRINTF(x,...)
Definition: trace.hh:229
Emulation of the Tsunami CChip CSRs.
#define TSDEV_CC_MPR2
Definition: tsunamireg.h:59
#define TSDEV_CC_MISC
Definition: tsunamireg.h:43
Bitfield< 7 > i
Tsunami * tsunami
pointer to the tsunami object.
void postDRIR(uint32_t interrupt)
post an interrupt to the CPU.
void postRTC()
post an RTC interrupt to the CPU
void post(int cpu_id, int int_num, int index)
Definition: intr_control.cc:50
void reqIPI(uint64_t ipreq)
request an interrupt be posted to the CPU.
uint64_t drir
This register contains bits for each PCI interrupt that can occur.
TsunamiCChip(const Params *p)
Initialize the Tsunami CChip by setting all of the device register to 0.
Top level class for Tsunami Chipset emulation.
Definition: tsunami.hh:56
#define TSDEV_CC_MPR3
Definition: tsunamireg.h:60
uint64_t ipint
Indicator of which CPUs have an IPI interrupt.
#define TSDEV_CC_DRIR
Definition: tsunamireg.h:53
#define TSDEV_CC_IIC3
Definition: tsunamireg.h:67
static const int Max_CPUs
Max number of CPUs in a Tsunami.
Definition: tsunami.hh:60
uint64_t dim[Tsunami::Max_CPUs]
The dims are device interrupt mask registers.
TsunamiCChipParams Params
void clearIPI(uint64_t ipintr)
post an ipi interrupt to the CPU.
Definition: cprintf.cc:42
TsunamiCChip * cchip
Pointer to the Tsunami CChip.
Definition: tsunami.hh:72
#define TSDEV_CC_DIM0
Definition: tsunamireg.h:49
#define TSDEV_CC_MPR0
Definition: tsunamireg.h:57
#define TSDEV_CC_CSR
Definition: tsunamireg.h:41
void setLE(T v)
Set the value in the data pointer to v as little endian.
#define TSDEV_CC_MTR
Definition: tsunamireg.h:42
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
#define TSDEV_CC_AAR0
Definition: tsunamireg.h:45
#define TSDEV_CC_ITIR
Definition: tsunamireg.h:74
RequestPtr req
A pointer to the original request.
Definition: packet.hh:327
unsigned getSize() const
Definition: packet.hh:736
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:645
Addr pioSize
Size that the device&#39;s address range.
Definition: io_device.hh:160
void makeAtomicResponse()
Definition: packet.hh:949
uint64_t Tick
Tick count type.
Definition: types.hh:63
void serialize(CheckpointOut &cp) const override
Serialize an object.
#define TSDEV_CC_DIR1
Definition: tsunamireg.h:52
Declaration of top level class for the Tsunami chipset.
#define TSDEV_CC_IPIQ
Definition: tsunamireg.h:72
std::vector< ThreadContext * > threadContexts
Definition: system.hh:190
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:658
Addr getAddr() const
Definition: packet.hh:726
void clearITI(uint64_t itintr)
clear a timer interrupt previously posted to the CPU.
#define TSDEV_CC_MPR1
Definition: tsunamireg.h:58
Port Object Declaration.
#define TSDEV_CC_IPIR
Definition: tsunamireg.h:73
void unserialize(CheckpointIn &cp) override
Unserialize an object.
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
#define TSDEV_CC_BDIRS
Definition: tsunamireg.h:71
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
#define TSDEV_CC_DIM3
Definition: tsunamireg.h:63
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:643
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:661
Tsunami CChip CSR Emulation.
#define TSDEV_CC_IIC2
Definition: tsunamireg.h:66
#define TSDEV_CC_IIC1
Definition: tsunamireg.h:56
Declaration of the Packet class.
std::ostream CheckpointOut
Definition: serialize.hh:68
List of Tsunami CSRs.
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:163
uint64_t dir[Tsunami::Max_CPUs]
The dirs are device interrupt registers.
#define TSDEV_CC_AAR1
Definition: tsunamireg.h:46
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
void clearDRIR(uint32_t interrupt)
clear an interrupt previously posted to the CPU.
#define TSDEV_CC_DIR2
Definition: tsunamireg.h:64
#define warn(...)
Definition: logging.hh:212
#define TSDEV_CC_AAR3
Definition: tsunamireg.h:48
void clear(int cpu_id, int int_num, int index)
Definition: intr_control.cc:59
uint64_t itint
Indicator of which CPUs have an RTC interrupt.
Bitfield< 0 > p
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:157
Bitfield< 1 > x
Definition: types.hh:105
#define TSDEV_CC_BDIMS
Definition: tsunamireg.h:70
#define TSDEV_CC_DIR0
Definition: tsunamireg.h:51
#define TSDEV_CC_DIM1
Definition: tsunamireg.h:50
#define TSDEV_CC_IIC0
Definition: tsunamireg.h:55
#define TSDEV_CC_DIM2
Definition: tsunamireg.h:62
#define TSDEV_CC_AAR2
Definition: tsunamireg.h:47
#define TSDEV_CC_DIR3
Definition: tsunamireg.h:65
#define TSDEV_CC_PRBEN
Definition: tsunamireg.h:54

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