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