tsunami_cchip.cc revision 909
1/* 2 * Copyright (c) 2004 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 29/* @file 30 * Emulation of the Tsunami CChip CSRs 31 */ 32 33#include <deque> 34#include <string> 35#include <vector> 36 37#include "base/trace.hh" 38#include "dev/console.hh" 39#include "dev/tsunami_cchip.hh" 40#include "dev/tsunamireg.h" 41#include "dev/tsunami.hh" 42#include "mem/bus/bus.hh" 43#include "mem/bus/pio_interface.hh" 44#include "mem/bus/pio_interface_impl.hh" 45#include "mem/functional_mem/memory_control.hh" 46#include "cpu/intr_control.hh" 47#include "sim/builder.hh" 48#include "sim/system.hh" 49 50using namespace std; 51 52TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, 53 MemoryController *mmu, HierParams *hier, Bus* bus) 54 : PioDevice(name), addr(a), tsunami(t) 55{ 56 mmu->add_child(this, Range<Addr>(addr, addr + size)); 57 58 for(int i=0; i < Tsunami::Max_CPUs; i++) { 59 dim[i] = 0; 60 dir[i] = 0; 61 dirInterrupting[i] = false; 62 ipiInterrupting[i] = false; 63 RTCInterrupting[i] = false; 64 } 65 66 if (bus) { 67 pioInterface = newPioInterface(name, hier, bus, this, 68 &TsunamiCChip::cacheAccess); 69 pioInterface->addAddrRange(addr, addr + size - 1); 70 } 71 72 drir = 0; 73 misc = 0; 74 75 //Put back pointer in tsunami 76 tsunami->cchip = this; 77} 78 79Fault 80TsunamiCChip::read(MemReqPtr &req, uint8_t *data) 81{ 82 DPRINTF(Tsunami, "read va=%#x size=%d\n", 83 req->vaddr, req->size); 84 85 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 86 ExecContext *xc = req->xc; 87 88 switch (req->size) { 89 90 case sizeof(uint64_t): 91 switch(daddr) { 92 case TSDEV_CC_CSR: 93 *(uint64_t*)data = 0x0; 94 return No_Fault; 95 case TSDEV_CC_MTR: 96 panic("TSDEV_CC_MTR not implemeted\n"); 97 return No_Fault; 98 case TSDEV_CC_MISC: 99 *(uint64_t*)data = misc | (xc->cpu_id & 0x3); 100 return No_Fault; 101 case TSDEV_CC_AAR0: 102 case TSDEV_CC_AAR1: 103 case TSDEV_CC_AAR2: 104 case TSDEV_CC_AAR3: 105 *(uint64_t*)data = 0; 106 return No_Fault; 107 case TSDEV_CC_DIM0: 108 *(uint64_t*)data = dim[0]; 109 return No_Fault; 110 case TSDEV_CC_DIM1: 111 *(uint64_t*)data = dim[1]; 112 return No_Fault; 113 case TSDEV_CC_DIM2: 114 *(uint64_t*)data = dim[2]; 115 return No_Fault; 116 case TSDEV_CC_DIM3: 117 *(uint64_t*)data = dim[3]; 118 return No_Fault; 119 case TSDEV_CC_DIR0: 120 *(uint64_t*)data = dir[0]; 121 return No_Fault; 122 case TSDEV_CC_DIR1: 123 *(uint64_t*)data = dir[1]; 124 return No_Fault; 125 case TSDEV_CC_DIR2: 126 *(uint64_t*)data = dir[2]; 127 return No_Fault; 128 case TSDEV_CC_DIR3: 129 *(uint64_t*)data = dir[3]; 130 return No_Fault; 131 case TSDEV_CC_DRIR: 132 *(uint64_t*)data = drir; 133 return No_Fault; 134 case TSDEV_CC_PRBEN: 135 panic("TSDEV_CC_PRBEN not implemented\n"); 136 return No_Fault; 137 case TSDEV_CC_IIC0: 138 case TSDEV_CC_IIC1: 139 case TSDEV_CC_IIC2: 140 case TSDEV_CC_IIC3: 141 panic("TSDEV_CC_IICx not implemented\n"); 142 return No_Fault; 143 case TSDEV_CC_MPR0: 144 case TSDEV_CC_MPR1: 145 case TSDEV_CC_MPR2: 146 case TSDEV_CC_MPR3: 147 panic("TSDEV_CC_MPRx not implemented\n"); 148 return No_Fault; 149 default: 150 panic("default in cchip read reached, accessing 0x%x\n"); 151 } // uint64_t 152 153 break; 154 case sizeof(uint32_t): 155 case sizeof(uint16_t): 156 case sizeof(uint8_t): 157 default: 158 panic("invalid access size(?) for tsunami register!\n"); 159 } 160 DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); 161 162 return No_Fault; 163} 164 165Fault 166TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) 167{ 168 DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n", 169 req->vaddr, *(uint64_t*)data, req->size); 170 171 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 172 173 bool supportedWrite = false; 174 uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); 175 176 switch (req->size) { 177 178 case sizeof(uint64_t): 179 switch(daddr) { 180 case TSDEV_CC_CSR: 181 panic("TSDEV_CC_CSR write\n"); 182 return No_Fault; 183 case TSDEV_CC_MTR: 184 panic("TSDEV_CC_MTR write not implemented\n"); 185 return No_Fault; 186 case TSDEV_CC_MISC: 187 //If it is the 4-7th bit, clear the RTC interrupt 188 uint64_t itintr; 189 if ((itintr = (*(uint64_t*) data) & (0xf<<4))) { 190 //Clear the bits in ITINTR 191 misc &= ~(itintr); 192 for (int i=0; i < size; i++) { 193 if ((itintr & (1 << (i+4))) && RTCInterrupting[i]) { 194 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0); 195 RTCInterrupting[i] = false; 196 DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i); 197 } 198 } 199 supportedWrite = true; 200 } 201 //If it is 12th-15th bit, IPI sent to Processor 1 202 uint64_t ipreq; 203 if ((ipreq = (*(uint64_t*) data) & (0xf << 12))) { 204 //Set the bits in IPINTR 205 misc |= (ipreq >> 4); 206 for (int i=0; i < size; i++) { 207 if ((ipreq & (1 << (i + 12)))) { 208 if (!ipiInterrupting[i]) 209 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ3, 0); 210 ipiInterrupting[i]++; 211 DPRINTF(IPI, "send cpu=%d pending=%d from=%d\n", i, 212 ipiInterrupting[i], req->cpu_num); 213 } 214 } 215 supportedWrite = true; 216 } 217 //If it is bits 8-11, then clearing IPI's 218 uint64_t ipintr; 219 if ((ipintr = (*(uint64_t*) data) & (0xf << 8))) { 220 //Clear the bits in IPINTR 221 misc &= ~(ipintr); 222 for (int i=0; i < size; i++) { 223 if ((ipintr & (1 << (i + 8))) && ipiInterrupting[i]) { 224 if (!(--ipiInterrupting[i])) 225 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ3, 0); 226 DPRINTF(IPI, "clearing cpu=%d pending=%d from=%d\n", i, 227 ipiInterrupting[i] + 1, req->cpu_num); 228 } 229 } 230 supportedWrite = true; 231 } 232 233 // ignore NXMs 234 if (*(uint64_t*)data & 0x10000000) 235 supportedWrite = true; 236 237 if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n"); 238 return No_Fault; 239 case TSDEV_CC_AAR0: 240 case TSDEV_CC_AAR1: 241 case TSDEV_CC_AAR2: 242 case TSDEV_CC_AAR3: 243 panic("TSDEV_CC_AARx write not implemeted\n"); 244 return No_Fault; 245 case TSDEV_CC_DIM0: 246 case TSDEV_CC_DIM1: 247 case TSDEV_CC_DIM2: 248 case TSDEV_CC_DIM3: 249 int number; 250 if(daddr == TSDEV_CC_DIM0) 251 number = 0; 252 else if(daddr == TSDEV_CC_DIM1) 253 number = 1; 254 else if(daddr == TSDEV_CC_DIM2) 255 number = 2; 256 else 257 number = 3; 258 259 uint64_t bitvector; 260 uint64_t olddim; 261 uint64_t olddir; 262 263 olddim = dim[number]; 264 olddir = dir[number]; 265 dim[number] = *(uint64_t*)data; 266 dir[number] = dim[number] & drir; 267 for(int x = 0; x < 64; x++) 268 { 269 bitvector = (uint64_t)1 << x; 270 // Figure out which bits have changed 271 if ((dim[number] & bitvector) != (olddim & bitvector)) 272 { 273 // The bit is now set and it wasn't before (set) 274 if((dim[number] & bitvector) && (dir[number] & bitvector)) 275 { 276 tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x); 277 DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n"); 278 } 279 else if ((olddir & bitvector) && 280 !(dir[number] & bitvector)) 281 { 282 // The bit was set and now its now clear and 283 // we were interrupting on that bit before 284 tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x); 285 DPRINTF(Tsunami, "dim write resulting in clear" 286 "dir interrupt to cpu 0\n"); 287 288 } 289 290 291 } 292 } 293 return No_Fault; 294 case TSDEV_CC_DIR0: 295 case TSDEV_CC_DIR1: 296 case TSDEV_CC_DIR2: 297 case TSDEV_CC_DIR3: 298 panic("TSDEV_CC_DIR write not implemented\n"); 299 case TSDEV_CC_DRIR: 300 panic("TSDEV_CC_DRIR write not implemented\n"); 301 case TSDEV_CC_PRBEN: 302 panic("TSDEV_CC_PRBEN write not implemented\n"); 303 case TSDEV_CC_IIC0: 304 case TSDEV_CC_IIC1: 305 case TSDEV_CC_IIC2: 306 case TSDEV_CC_IIC3: 307 panic("TSDEV_CC_IICx write not implemented\n"); 308 case TSDEV_CC_MPR0: 309 case TSDEV_CC_MPR1: 310 case TSDEV_CC_MPR2: 311 case TSDEV_CC_MPR3: 312 panic("TSDEV_CC_MPRx write not implemented\n"); 313 default: 314 panic("default in cchip read reached, accessing 0x%x\n"); 315 } 316 317 break; 318 case sizeof(uint32_t): 319 case sizeof(uint16_t): 320 case sizeof(uint8_t): 321 default: 322 panic("invalid access size(?) for tsunami register!\n"); 323 } 324 325 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); 326 327 return No_Fault; 328} 329 330void 331TsunamiCChip::postRTC() 332{ 333 int size = tsunami->intrctrl->cpu->system->execContexts.size(); 334 335 for (int i = 0; i < size; i++) { 336 if (!RTCInterrupting[i]) { 337 misc |= 16 << i; 338 RTCInterrupting[i] = true; 339 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0); 340 DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i); 341 } 342 } 343 344} 345 346void 347TsunamiCChip::postDRIR(uint32_t interrupt) 348{ 349 uint64_t bitvector = (uint64_t)0x1 << interrupt; 350 drir |= bitvector; 351 uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); 352 for(int i=0; i < size; i++) { 353 dir[i] = dim[i] & drir; 354 if (dim[i] & bitvector) { 355 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt); 356 DPRINTF(Tsunami, "posting dir interrupt to cpu %d," 357 "interrupt %d\n",i, interrupt); 358 } 359 } 360} 361 362void 363TsunamiCChip::clearDRIR(uint32_t interrupt) 364{ 365 uint64_t bitvector = (uint64_t)0x1 << interrupt; 366 uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); 367 if (drir & bitvector) 368 { 369 drir &= ~bitvector; 370 for(int i=0; i < size; i++) { 371 if (dir[i] & bitvector) { 372 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt); 373 DPRINTF(Tsunami, "clearing dir interrupt to cpu %d," 374 "interrupt %d\n",i, interrupt); 375 376 } 377 dir[i] = dim[i] & drir; 378 } 379 } 380 else 381 DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt); 382} 383 384Tick 385TsunamiCChip::cacheAccess(MemReqPtr &req) 386{ 387 return curTick + 1000; 388} 389 390 391void 392TsunamiCChip::serialize(std::ostream &os) 393{ 394 SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); 395 SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); 396 SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); 397 SERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs); 398 SERIALIZE_SCALAR(drir); 399 SERIALIZE_SCALAR(misc); 400 SERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs); 401} 402 403void 404TsunamiCChip::unserialize(Checkpoint *cp, const std::string §ion) 405{ 406 UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); 407 UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); 408 UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); 409 UNSERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs); 410 UNSERIALIZE_SCALAR(drir); 411 UNSERIALIZE_SCALAR(misc); 412 UNSERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs); 413} 414 415BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) 416 417 SimObjectParam<Tsunami *> tsunami; 418 SimObjectParam<MemoryController *> mmu; 419 Param<Addr> addr; 420 SimObjectParam<Bus*> io_bus; 421 SimObjectParam<HierParams *> hier; 422 423END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) 424 425BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) 426 427 INIT_PARAM(tsunami, "Tsunami"), 428 INIT_PARAM(mmu, "Memory Controller"), 429 INIT_PARAM(addr, "Device Address"), 430 INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL), 431 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) 432 433END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) 434 435CREATE_SIM_OBJECT(TsunamiCChip) 436{ 437 return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu, hier, io_bus); 438} 439 440REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip) 441