tsunami_cchip.cc revision 909
16691Stjones1@inf.ed.ac.uk/* 26691Stjones1@inf.ed.ac.uk * Copyright (c) 2004 The Regents of The University of Michigan 36691Stjones1@inf.ed.ac.uk * All rights reserved. 46691Stjones1@inf.ed.ac.uk * 56691Stjones1@inf.ed.ac.uk * Redistribution and use in source and binary forms, with or without 66691Stjones1@inf.ed.ac.uk * modification, are permitted provided that the following conditions are 76691Stjones1@inf.ed.ac.uk * met: redistributions of source code must retain the above copyright 86691Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer; 96691Stjones1@inf.ed.ac.uk * redistributions in binary form must reproduce the above copyright 106691Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer in the 116691Stjones1@inf.ed.ac.uk * documentation and/or other materials provided with the distribution; 126691Stjones1@inf.ed.ac.uk * neither the name of the copyright holders nor the names of its 136691Stjones1@inf.ed.ac.uk * contributors may be used to endorse or promote products derived from 146691Stjones1@inf.ed.ac.uk * this software without specific prior written permission. 156691Stjones1@inf.ed.ac.uk * 166691Stjones1@inf.ed.ac.uk * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176691Stjones1@inf.ed.ac.uk * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186691Stjones1@inf.ed.ac.uk * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196691Stjones1@inf.ed.ac.uk * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206691Stjones1@inf.ed.ac.uk * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216691Stjones1@inf.ed.ac.uk * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226691Stjones1@inf.ed.ac.uk * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236691Stjones1@inf.ed.ac.uk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246691Stjones1@inf.ed.ac.uk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256691Stjones1@inf.ed.ac.uk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266691Stjones1@inf.ed.ac.uk * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276691Stjones1@inf.ed.ac.uk */ 286691Stjones1@inf.ed.ac.uk 296691Stjones1@inf.ed.ac.uk/* @file 306691Stjones1@inf.ed.ac.uk * Emulation of the Tsunami CChip CSRs 316691Stjones1@inf.ed.ac.uk */ 326691Stjones1@inf.ed.ac.uk 336691Stjones1@inf.ed.ac.uk#include <deque> 346691Stjones1@inf.ed.ac.uk#include <string> 356691Stjones1@inf.ed.ac.uk#include <vector> 366691Stjones1@inf.ed.ac.uk 376691Stjones1@inf.ed.ac.uk#include "base/trace.hh" 386691Stjones1@inf.ed.ac.uk#include "dev/console.hh" 396691Stjones1@inf.ed.ac.uk#include "dev/tsunami_cchip.hh" 406691Stjones1@inf.ed.ac.uk#include "dev/tsunamireg.h" 416691Stjones1@inf.ed.ac.uk#include "dev/tsunami.hh" 426691Stjones1@inf.ed.ac.uk#include "mem/bus/bus.hh" 436691Stjones1@inf.ed.ac.uk#include "mem/bus/pio_interface.hh" 446691Stjones1@inf.ed.ac.uk#include "mem/bus/pio_interface_impl.hh" 456691Stjones1@inf.ed.ac.uk#include "mem/functional_mem/memory_control.hh" 466691Stjones1@inf.ed.ac.uk#include "cpu/intr_control.hh" 477512Stjones1@inf.ed.ac.uk#include "sim/builder.hh" 487512Stjones1@inf.ed.ac.uk#include "sim/system.hh" 497512Stjones1@inf.ed.ac.uk 507512Stjones1@inf.ed.ac.ukusing namespace std; 517512Stjones1@inf.ed.ac.uk 527512Stjones1@inf.ed.ac.ukTsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, 536691Stjones1@inf.ed.ac.uk MemoryController *mmu, HierParams *hier, Bus* bus) 546691Stjones1@inf.ed.ac.uk : PioDevice(name), addr(a), tsunami(t) 556691Stjones1@inf.ed.ac.uk{ 566691Stjones1@inf.ed.ac.uk mmu->add_child(this, Range<Addr>(addr, addr + size)); 576691Stjones1@inf.ed.ac.uk 586691Stjones1@inf.ed.ac.uk for(int i=0; i < Tsunami::Max_CPUs; i++) { 596691Stjones1@inf.ed.ac.uk dim[i] = 0; 606691Stjones1@inf.ed.ac.uk dir[i] = 0; 616691Stjones1@inf.ed.ac.uk dirInterrupting[i] = false; 626691Stjones1@inf.ed.ac.uk ipiInterrupting[i] = false; 636691Stjones1@inf.ed.ac.uk RTCInterrupting[i] = false; 646691Stjones1@inf.ed.ac.uk } 656691Stjones1@inf.ed.ac.uk 666691Stjones1@inf.ed.ac.uk if (bus) { 676691Stjones1@inf.ed.ac.uk pioInterface = newPioInterface(name, hier, bus, this, 686691Stjones1@inf.ed.ac.uk &TsunamiCChip::cacheAccess); 696691Stjones1@inf.ed.ac.uk pioInterface->addAddrRange(addr, addr + size - 1); 706691Stjones1@inf.ed.ac.uk } 716691Stjones1@inf.ed.ac.uk 726691Stjones1@inf.ed.ac.uk drir = 0; 736691Stjones1@inf.ed.ac.uk misc = 0; 746691Stjones1@inf.ed.ac.uk 756691Stjones1@inf.ed.ac.uk //Put back pointer in tsunami 766691Stjones1@inf.ed.ac.uk tsunami->cchip = this; 776691Stjones1@inf.ed.ac.uk} 786691Stjones1@inf.ed.ac.uk 796691Stjones1@inf.ed.ac.ukFault 806691Stjones1@inf.ed.ac.ukTsunamiCChip::read(MemReqPtr &req, uint8_t *data) 816691Stjones1@inf.ed.ac.uk{ 826691Stjones1@inf.ed.ac.uk DPRINTF(Tsunami, "read va=%#x size=%d\n", 836691Stjones1@inf.ed.ac.uk req->vaddr, req->size); 846691Stjones1@inf.ed.ac.uk 856691Stjones1@inf.ed.ac.uk Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 866691Stjones1@inf.ed.ac.uk ExecContext *xc = req->xc; 876691Stjones1@inf.ed.ac.uk 886691Stjones1@inf.ed.ac.uk switch (req->size) { 896691Stjones1@inf.ed.ac.uk 906691Stjones1@inf.ed.ac.uk case sizeof(uint64_t): 916691Stjones1@inf.ed.ac.uk switch(daddr) { 926691Stjones1@inf.ed.ac.uk case TSDEV_CC_CSR: 936691Stjones1@inf.ed.ac.uk *(uint64_t*)data = 0x0; 946691Stjones1@inf.ed.ac.uk return No_Fault; 956691Stjones1@inf.ed.ac.uk case TSDEV_CC_MTR: 966691Stjones1@inf.ed.ac.uk panic("TSDEV_CC_MTR not implemeted\n"); 976691Stjones1@inf.ed.ac.uk return No_Fault; 986691Stjones1@inf.ed.ac.uk case TSDEV_CC_MISC: 996691Stjones1@inf.ed.ac.uk *(uint64_t*)data = misc | (xc->cpu_id & 0x3); 1006691Stjones1@inf.ed.ac.uk 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