tsunami_cchip.cc revision 831
12391SN/A/* $Id$ */ 28931Sandreas.hansson@arm.com 38931Sandreas.hansson@arm.com/* @file 48931Sandreas.hansson@arm.com * Emulation of the Tsunami CChip CSRs 58931Sandreas.hansson@arm.com */ 68931Sandreas.hansson@arm.com 78931Sandreas.hansson@arm.com#include <deque> 88931Sandreas.hansson@arm.com#include <string> 98931Sandreas.hansson@arm.com#include <vector> 108931Sandreas.hansson@arm.com 118931Sandreas.hansson@arm.com#include "base/trace.hh" 128931Sandreas.hansson@arm.com#include "cpu/exec_context.hh" 132391SN/A#include "dev/console.hh" 142391SN/A#include "dev/tsunami_cchip.hh" 152391SN/A#include "dev/tsunamireg.h" 162391SN/A#include "dev/tsunami.hh" 172391SN/A#include "cpu/intr_control.hh" 182391SN/A#include "mem/functional_mem/memory_control.hh" 192391SN/A#include "sim/builder.hh" 202391SN/A#include "sim/system.hh" 212391SN/A 222391SN/Ausing namespace std; 232391SN/A 242391SN/ATsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, 252391SN/A MemoryController *mmu) 262391SN/A : FunctionalMemory(name), addr(a), tsunami(t) 272391SN/A{ 282391SN/A mmu->add_child(this, Range<Addr>(addr, addr + size)); 292391SN/A 302391SN/A for(int i=0; i < Tsunami::Max_CPUs; i++) { 312391SN/A dim[i] = 0; 322391SN/A dir[i] = 0; 332391SN/A dirInterrupting[i] = false; 342391SN/A ipiInterrupting[i] = false; 352391SN/A RTCInterrupting[i] = false; 362665Ssaidi@eecs.umich.edu } 378931Sandreas.hansson@arm.com 382391SN/A drir = 0; 392391SN/A misc = 0; 4010482Sandreas.hansson@arm.com 4110482Sandreas.hansson@arm.com //Put back pointer in tsunami 422391SN/A tsunami->cchip = this; 439235Sandreas.hansson@arm.com} 4410482Sandreas.hansson@arm.com 459293Sandreas.hansson@arm.comFault 469293Sandreas.hansson@arm.comTsunamiCChip::read(MemReqPtr &req, uint8_t *data) 479293Sandreas.hansson@arm.com{ 489293Sandreas.hansson@arm.com DPRINTF(Tsunami, "read va=%#x size=%d\n", 499293Sandreas.hansson@arm.com req->vaddr, req->size); 504762Snate@binkert.org 518931Sandreas.hansson@arm.com Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 528931Sandreas.hansson@arm.com ExecContext *xc = req->xc; 538931Sandreas.hansson@arm.com 548931Sandreas.hansson@arm.com switch (req->size) { 559293Sandreas.hansson@arm.com 569293Sandreas.hansson@arm.com case sizeof(uint64_t): 579293Sandreas.hansson@arm.com switch(daddr) { 589293Sandreas.hansson@arm.com case TSDEV_CC_CSR: 599293Sandreas.hansson@arm.com *(uint64_t*)data = 0x0; 6010482Sandreas.hansson@arm.com return No_Fault; 619293Sandreas.hansson@arm.com case TSDEV_CC_MTR: 629293Sandreas.hansson@arm.com panic("TSDEV_CC_MTR not implemeted\n"); 639293Sandreas.hansson@arm.com return No_Fault; 649293Sandreas.hansson@arm.com case TSDEV_CC_MISC: 659293Sandreas.hansson@arm.com *(uint64_t*)data = misc | (xc->cpu_id & 0x3); 668931Sandreas.hansson@arm.com return No_Fault; 679293Sandreas.hansson@arm.com case TSDEV_CC_AAR0: 682391SN/A case TSDEV_CC_AAR1: 692413SN/A case TSDEV_CC_AAR2: 702391SN/A case TSDEV_CC_AAR3: 712391SN/A panic("TSDEV_CC_AARx not implemeted\n"); 729293Sandreas.hansson@arm.com return No_Fault; 739293Sandreas.hansson@arm.com case TSDEV_CC_DIM0: 749293Sandreas.hansson@arm.com *(uint64_t*)data = dim[0]; 758931Sandreas.hansson@arm.com return No_Fault; 769235Sandreas.hansson@arm.com case TSDEV_CC_DIM1: 773170Sstever@eecs.umich.edu *(uint64_t*)data = dim[1]; 7810699Sandreas.hansson@arm.com return No_Fault; 7910699Sandreas.hansson@arm.com case TSDEV_CC_DIM2: 8010699Sandreas.hansson@arm.com *(uint64_t*)data = dim[2]; 813170Sstever@eecs.umich.edu return No_Fault; 828931Sandreas.hansson@arm.com case TSDEV_CC_DIM3: 838931Sandreas.hansson@arm.com *(uint64_t*)data = dim[3]; 843170Sstever@eecs.umich.edu return No_Fault; 858931Sandreas.hansson@arm.com case TSDEV_CC_DIR0: 868931Sandreas.hansson@arm.com *(uint64_t*)data = dir[0]; 873170Sstever@eecs.umich.edu return No_Fault; 8810700Sandreas.hansson@arm.com case TSDEV_CC_DIR1: 8910700Sandreas.hansson@arm.com *(uint64_t*)data = dir[1]; 9010700Sandreas.hansson@arm.com return No_Fault; 919293Sandreas.hansson@arm.com case TSDEV_CC_DIR2: 929293Sandreas.hansson@arm.com *(uint64_t*)data = dir[2]; 9310482Sandreas.hansson@arm.com return No_Fault; 949293Sandreas.hansson@arm.com case TSDEV_CC_DIR3: 958931Sandreas.hansson@arm.com *(uint64_t*)data = dir[3]; 968931Sandreas.hansson@arm.com return No_Fault; 973170Sstever@eecs.umich.edu case TSDEV_CC_DRIR: 988931Sandreas.hansson@arm.com *(uint64_t*)data = drir; 998931Sandreas.hansson@arm.com return No_Fault; 1008719SAli.Saidi@ARM.com case TSDEV_CC_PRBEN: 1019293Sandreas.hansson@arm.com panic("TSDEV_CC_PRBEN not implemented\n"); 1029293Sandreas.hansson@arm.com return No_Fault; 1039293Sandreas.hansson@arm.com case TSDEV_CC_IIC0: 1049293Sandreas.hansson@arm.com case TSDEV_CC_IIC1: 1059293Sandreas.hansson@arm.com case TSDEV_CC_IIC2: 1069293Sandreas.hansson@arm.com case TSDEV_CC_IIC3: 1079293Sandreas.hansson@arm.com panic("TSDEV_CC_IICx not implemented\n"); 1089293Sandreas.hansson@arm.com return No_Fault; 1099293Sandreas.hansson@arm.com case TSDEV_CC_MPR0: 1109293Sandreas.hansson@arm.com case TSDEV_CC_MPR1: 1119293Sandreas.hansson@arm.com case TSDEV_CC_MPR2: 1122391SN/A case TSDEV_CC_MPR3: 1132391SN/A panic("TSDEV_CC_MPRx not implemented\n"); 1148931Sandreas.hansson@arm.com return No_Fault; 1158931Sandreas.hansson@arm.com default: 1168931Sandreas.hansson@arm.com panic("default in cchip read reached, accessing 0x%x\n"); 1179293Sandreas.hansson@arm.com } // uint64_t 11810700Sandreas.hansson@arm.com 11910700Sandreas.hansson@arm.com break; 1202391SN/A case sizeof(uint32_t): 1218931Sandreas.hansson@arm.com case sizeof(uint16_t): 1229293Sandreas.hansson@arm.com case sizeof(uint8_t): 1238931Sandreas.hansson@arm.com default: 1249293Sandreas.hansson@arm.com panic("invalid access size(?) for tsunami register!\n"); 1259293Sandreas.hansson@arm.com } 1269293Sandreas.hansson@arm.com DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); 1279293Sandreas.hansson@arm.com 1289293Sandreas.hansson@arm.com return No_Fault; 1299293Sandreas.hansson@arm.com} 1309293Sandreas.hansson@arm.com 1314762Snate@binkert.orgFault 1328931Sandreas.hansson@arm.comTsunamiCChip::write(MemReqPtr &req, const uint8_t *data) 1338931Sandreas.hansson@arm.com{ 1348931Sandreas.hansson@arm.com DPRINTF(Tsunami, "write - va=%#x size=%d \n", 1358931Sandreas.hansson@arm.com req->vaddr, req->size); 1368931Sandreas.hansson@arm.com 1378931Sandreas.hansson@arm.com Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 1388931Sandreas.hansson@arm.com 1398931Sandreas.hansson@arm.com bool supportedWrite = false; 1402391SN/A uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); 1418931Sandreas.hansson@arm.com 1428931Sandreas.hansson@arm.com switch (req->size) { 1439413Sandreas.hansson@arm.com 1449413Sandreas.hansson@arm.com case sizeof(uint64_t): 1459413Sandreas.hansson@arm.com switch(daddr) { 1468931Sandreas.hansson@arm.com case TSDEV_CC_CSR: 1478931Sandreas.hansson@arm.com panic("TSDEV_CC_CSR write\n"); 1488931Sandreas.hansson@arm.com return No_Fault; 1498931Sandreas.hansson@arm.com case TSDEV_CC_MTR: 1508923Sandreas.hansson@arm.com panic("TSDEV_CC_MTR write not implemented\n"); 1518931Sandreas.hansson@arm.com return No_Fault; 1528931Sandreas.hansson@arm.com case TSDEV_CC_MISC: 1538931Sandreas.hansson@arm.com //If it is the 4-7th bit, clear the RTC interrupt 1548931Sandreas.hansson@arm.com uint64_t itintr; 1558931Sandreas.hansson@arm.com if ((itintr = (*(uint64_t*) data) & (0xf<<4))) { 1568931Sandreas.hansson@arm.com //Clear the bits in ITINTR 1578923Sandreas.hansson@arm.com misc &= ~(itintr); 1589293Sandreas.hansson@arm.com for (int i=0; i < size; i++) { 1599293Sandreas.hansson@arm.com if ((itintr & (1 << (i+4))) && RTCInterrupting[i]) { 1609293Sandreas.hansson@arm.com tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0); 1619293Sandreas.hansson@arm.com RTCInterrupting[i] = false; 1629293Sandreas.hansson@arm.com DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i); 1639293Sandreas.hansson@arm.com } 1649293Sandreas.hansson@arm.com } 1659293Sandreas.hansson@arm.com supportedWrite = true; 1669293Sandreas.hansson@arm.com } 1679293Sandreas.hansson@arm.com //If it is 12th-15th bit, IPI sent to Processor 1 1689293Sandreas.hansson@arm.com uint64_t ipreq; 1699293Sandreas.hansson@arm.com if ((ipreq = (*(uint64_t*) data) & (0xf << 12))) { 17010482Sandreas.hansson@arm.com //Set the bits in IPINTR 1719293Sandreas.hansson@arm.com misc |= (ipreq >> 4); 1729293Sandreas.hansson@arm.com for (int i=0; i < size; i++) { 1738931Sandreas.hansson@arm.com if ((ipreq & (1 << (i + 12)))) { 1749293Sandreas.hansson@arm.com if (!ipiInterrupting[i]) 1759293Sandreas.hansson@arm.com tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ3, 0); 1769293Sandreas.hansson@arm.com ipiInterrupting[i]++; 1778931Sandreas.hansson@arm.com DPRINTF(IPI, "send cpu=%d pending=%d from=%d\n", i, 1789293Sandreas.hansson@arm.com ipiInterrupting[i], req->cpu_num); 1798719SAli.Saidi@ARM.com } 1808931Sandreas.hansson@arm.com } 1819293Sandreas.hansson@arm.com supportedWrite = true; 1829293Sandreas.hansson@arm.com } 1839293Sandreas.hansson@arm.com //If it is bits 8-11, then clearing IPI's 1849293Sandreas.hansson@arm.com uint64_t ipintr; 1859293Sandreas.hansson@arm.com if ((ipintr = (*(uint64_t*) data) & (0xf << 8))) { 1869293Sandreas.hansson@arm.com //Clear the bits in IPINTR 1879293Sandreas.hansson@arm.com misc &= ~(ipintr); 1889293Sandreas.hansson@arm.com for (int i=0; i < size; i++) { 1899293Sandreas.hansson@arm.com if ((ipintr & (1 << (i + 8))) && ipiInterrupting[i]) { 1908931Sandreas.hansson@arm.com if (!(--ipiInterrupting[i])) 1919293Sandreas.hansson@arm.com tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ3, 0); 1929293Sandreas.hansson@arm.com DPRINTF(IPI, "clearing cpu=%d pending=%d from=%d\n", i, 1939293Sandreas.hansson@arm.com ipiInterrupting[i] + 1, req->cpu_num); 1949293Sandreas.hansson@arm.com } 1959293Sandreas.hansson@arm.com } 1969293Sandreas.hansson@arm.com supportedWrite = true; 1979293Sandreas.hansson@arm.com } 1989293Sandreas.hansson@arm.com if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n"); 1999293Sandreas.hansson@arm.com return No_Fault; 20010905Sandreas.sandberg@arm.com case TSDEV_CC_AAR0: 2019293Sandreas.hansson@arm.com case TSDEV_CC_AAR1: 2029293Sandreas.hansson@arm.com case TSDEV_CC_AAR2: 2039293Sandreas.hansson@arm.com case TSDEV_CC_AAR3: 2049293Sandreas.hansson@arm.com panic("TSDEV_CC_AARx write not implemeted\n"); 2059293Sandreas.hansson@arm.com return No_Fault; 2069293Sandreas.hansson@arm.com case TSDEV_CC_DIM0: 2079293Sandreas.hansson@arm.com case TSDEV_CC_DIM1: 2089293Sandreas.hansson@arm.com case TSDEV_CC_DIM2: 20910905Sandreas.sandberg@arm.com case TSDEV_CC_DIM3: 21010905Sandreas.sandberg@arm.com int number; 2119293Sandreas.hansson@arm.com if(daddr == TSDEV_CC_DIM0) 2129293Sandreas.hansson@arm.com number = 0; 2139293Sandreas.hansson@arm.com else if(daddr == TSDEV_CC_DIM1) 2149293Sandreas.hansson@arm.com number = 1; 2159293Sandreas.hansson@arm.com else if(daddr == TSDEV_CC_DIM2) 2169293Sandreas.hansson@arm.com number = 2; 21710905Sandreas.sandberg@arm.com else 2189293Sandreas.hansson@arm.com number = 3; 2199293Sandreas.hansson@arm.com 2209293Sandreas.hansson@arm.com uint64_t bitvector; 2219293Sandreas.hansson@arm.com uint64_t olddim; 22210905Sandreas.sandberg@arm.com uint64_t olddir; 2239293Sandreas.hansson@arm.com 2242391SN/A olddim = dim[number]; 2252391SN/A olddir = dir[number]; 22610482Sandreas.hansson@arm.com dim[number] = *(uint64_t*)data; 227 dir[number] = dim[number] & drir; 228 for(int x = 0; x < 64; x++) 229 { 230 bitvector = (uint64_t)1 << x; 231 // Figure out which bits have changed 232 if ((dim[number] & bitvector) != (olddim & bitvector)) 233 { 234 // The bit is now set and it wasn't before (set) 235 if((dim[number] & bitvector) && (dir[number] & bitvector)) 236 { 237 tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x); 238 DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n"); 239 } 240 else if ((olddir & bitvector) && 241 !(dir[number] & bitvector)) 242 { 243 // The bit was set and now its now clear and 244 // we were interrupting on that bit before 245 tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x); 246 DPRINTF(Tsunami, "dim write resulting in clear" 247 "dir interrupt to cpu 0\n"); 248 249 } 250 251 252 } 253 } 254 return No_Fault; 255 case TSDEV_CC_DIR0: 256 case TSDEV_CC_DIR1: 257 case TSDEV_CC_DIR2: 258 case TSDEV_CC_DIR3: 259 panic("TSDEV_CC_DIR write not implemented\n"); 260 case TSDEV_CC_DRIR: 261 panic("TSDEV_CC_DRIR write not implemented\n"); 262 case TSDEV_CC_PRBEN: 263 panic("TSDEV_CC_PRBEN write not implemented\n"); 264 case TSDEV_CC_IIC0: 265 case TSDEV_CC_IIC1: 266 case TSDEV_CC_IIC2: 267 case TSDEV_CC_IIC3: 268 panic("TSDEV_CC_IICx write not implemented\n"); 269 case TSDEV_CC_MPR0: 270 case TSDEV_CC_MPR1: 271 case TSDEV_CC_MPR2: 272 case TSDEV_CC_MPR3: 273 panic("TSDEV_CC_MPRx write not implemented\n"); 274 default: 275 panic("default in cchip read reached, accessing 0x%x\n"); 276 } 277 278 break; 279 case sizeof(uint32_t): 280 case sizeof(uint16_t): 281 case sizeof(uint8_t): 282 default: 283 panic("invalid access size(?) for tsunami register!\n"); 284 } 285 286 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); 287 288 return No_Fault; 289} 290 291void 292TsunamiCChip::postRTC() 293{ 294 int size = tsunami->intrctrl->cpu->system->execContexts.size(); 295 296 for (int i = 0; i < size; i++) { 297 if (!RTCInterrupting[i]) { 298 misc |= 16 << i; 299 RTCInterrupting[i] = true; 300 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0); 301 DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i); 302 } 303 } 304 305} 306 307void 308TsunamiCChip::postDRIR(uint32_t interrupt) 309{ 310 uint64_t bitvector = (uint64_t)0x1 << interrupt; 311 drir |= bitvector; 312 uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); 313 for(int i=0; i < size; i++) { 314 dir[i] = dim[i] & drir; 315 if (dim[i] & bitvector) { 316 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt); 317 DPRINTF(Tsunami, "posting dir interrupt to cpu %d," 318 "interrupt %d\n",i, interrupt); 319 } 320 } 321} 322 323void 324TsunamiCChip::clearDRIR(uint32_t interrupt) 325{ 326 uint64_t bitvector = (uint64_t)0x1 << interrupt; 327 uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); 328 if (drir & bitvector) 329 { 330 drir &= ~bitvector; 331 for(int i=0; i < size; i++) { 332 if (dir[i] & bitvector) { 333 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt); 334 DPRINTF(Tsunami, "clearing dir interrupt to cpu %d," 335 "interrupt %d\n",i, interrupt); 336 337 } 338 dir[i] = dim[i] & drir; 339 } 340 } 341 else 342 DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt); 343} 344 345void 346TsunamiCChip::serialize(std::ostream &os) 347{ 348 SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); 349 SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); 350 SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); 351 SERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs); 352 SERIALIZE_SCALAR(drir); 353 SERIALIZE_SCALAR(misc); 354 SERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs); 355} 356 357void 358TsunamiCChip::unserialize(Checkpoint *cp, const std::string §ion) 359{ 360 UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); 361 UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); 362 UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); 363 UNSERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs); 364 UNSERIALIZE_SCALAR(drir); 365 UNSERIALIZE_SCALAR(misc); 366 UNSERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs); 367} 368 369BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) 370 371 SimObjectParam<Tsunami *> tsunami; 372 SimObjectParam<MemoryController *> mmu; 373 Param<Addr> addr; 374 375END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) 376 377BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) 378 379 INIT_PARAM(tsunami, "Tsunami"), 380 INIT_PARAM(mmu, "Memory Controller"), 381 INIT_PARAM(addr, "Device Address") 382 383END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) 384 385CREATE_SIM_OBJECT(TsunamiCChip) 386{ 387 return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu); 388} 389 390REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip) 391