tsunami_cchip.cc revision 830
1/* $Id$ */ 2 3/* @file 4 * Emulation of the Tsunami CChip CSRs 5 */ 6 7#include <deque> 8#include <string> 9#include <vector> 10 11#include "base/trace.hh" 12#include "cpu/exec_context.hh" 13#include "dev/console.hh" 14#include "dev/tsunami_cchip.hh" 15#include "dev/tsunamireg.h" 16#include "dev/tsunami.hh" 17#include "cpu/intr_control.hh" 18#include "mem/functional_mem/memory_control.hh" 19#include "sim/builder.hh" 20#include "sim/system.hh" 21 22using namespace std; 23 24TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, 25 MemoryController *mmu) 26 : FunctionalMemory(name), addr(a), tsunami(t) 27{ 28 mmu->add_child(this, Range<Addr>(addr, addr + size)); 29 30 for(int i=0; i < Tsunami::Max_CPUs; i++) { 31 dim[i] = 0; 32 dir[i] = 0; 33 dirInterrupting[i] = false; 34 ipiInterrupting[i] = false; 35 RTCInterrupting[i] = false; 36 } 37 38 drir = 0; 39 misc = 0; 40 41 //Put back pointer in tsunami 42 tsunami->cchip = this; 43} 44 45Fault 46TsunamiCChip::read(MemReqPtr &req, uint8_t *data) 47{ 48 DPRINTF(Tsunami, "read va=%#x size=%d\n", 49 req->vaddr, req->size); 50 51 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 52 ExecContext *xc = req->xc; 53 54 switch (req->size) { 55 56 case sizeof(uint64_t): 57 switch(daddr) { 58 case TSDEV_CC_CSR: 59 *(uint64_t*)data = 0x0; 60 return No_Fault; 61 case TSDEV_CC_MTR: 62 panic("TSDEV_CC_MTR not implemeted\n"); 63 return No_Fault; 64 case TSDEV_CC_MISC: 65 *(uint64_t*)data = misc | (xc->cpu_id & 0x3); 66 return No_Fault; 67 case TSDEV_CC_AAR0: 68 case TSDEV_CC_AAR1: 69 case TSDEV_CC_AAR2: 70 case TSDEV_CC_AAR3: 71 panic("TSDEV_CC_AARx not implemeted\n"); 72 return No_Fault; 73 case TSDEV_CC_DIM0: 74 *(uint64_t*)data = dim[0]; 75 return No_Fault; 76 case TSDEV_CC_DIM1: 77 *(uint64_t*)data = dim[1]; 78 return No_Fault; 79 case TSDEV_CC_DIM2: 80 *(uint64_t*)data = dim[2]; 81 return No_Fault; 82 case TSDEV_CC_DIM3: 83 *(uint64_t*)data = dim[3]; 84 return No_Fault; 85 case TSDEV_CC_DIR0: 86 *(uint64_t*)data = dir[0]; 87 return No_Fault; 88 case TSDEV_CC_DIR1: 89 *(uint64_t*)data = dir[1]; 90 return No_Fault; 91 case TSDEV_CC_DIR2: 92 *(uint64_t*)data = dir[2]; 93 return No_Fault; 94 case TSDEV_CC_DIR3: 95 *(uint64_t*)data = dir[3]; 96 return No_Fault; 97 case TSDEV_CC_DRIR: 98 *(uint64_t*)data = drir; 99 return No_Fault; 100 case TSDEV_CC_PRBEN: 101 panic("TSDEV_CC_PRBEN not implemented\n"); 102 return No_Fault; 103 case TSDEV_CC_IIC0: 104 case TSDEV_CC_IIC1: 105 case TSDEV_CC_IIC2: 106 case TSDEV_CC_IIC3: 107 panic("TSDEV_CC_IICx not implemented\n"); 108 return No_Fault; 109 case TSDEV_CC_MPR0: 110 case TSDEV_CC_MPR1: 111 case TSDEV_CC_MPR2: 112 case TSDEV_CC_MPR3: 113 panic("TSDEV_CC_MPRx not implemented\n"); 114 return No_Fault; 115 default: 116 panic("default in cchip read reached, accessing 0x%x\n"); 117 } // uint64_t 118 119 break; 120 case sizeof(uint32_t): 121 case sizeof(uint16_t): 122 case sizeof(uint8_t): 123 default: 124 panic("invalid access size(?) for tsunami register!\n"); 125 } 126 DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); 127 128 return No_Fault; 129} 130 131Fault 132TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) 133{ 134 DPRINTF(Tsunami, "write - va=%#x size=%d \n", 135 req->vaddr, req->size); 136 137 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 138 139 bool supportedWrite = false; 140 141 142 switch (req->size) { 143 144 case sizeof(uint64_t): 145 switch(daddr) { 146 case TSDEV_CC_CSR: 147 panic("TSDEV_CC_CSR write\n"); 148 return No_Fault; 149 case TSDEV_CC_MTR: 150 panic("TSDEV_CC_MTR write not implemented\n"); 151 return No_Fault; 152 case TSDEV_CC_MISC: 153 //If it is the 4-7th bit, clear the RTC interrupt 154 uint64_t itintr; 155 if ((itintr = (*(uint64_t*) data) & (0xf<<4))) { 156 //Clear the bits in ITINTR 157 misc &= ~(itintr); 158 for (int i=0; i < 4; i++) { 159 if ((itintr & (1 << (i+4))) && RTCInterrupting[i]) { 160 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0); 161 RTCInterrupting[i] = false; 162 DPRINTF(Tsunami, "clearing rtc interrupt\n"); 163 } 164 } 165 supportedWrite = true; 166 } 167 //If it is 12th-15th bit, IPI sent to Processor 1 168 uint64_t ipreq; 169 if ((ipreq = (*(uint64_t*) data) & (0xf << 12))) { 170 //Set the bits in IPINTR 171 misc |= (ipreq >> 4); 172 for (int i=0; i < 4; i++) { 173 if ((ipreq & (1 << (i + 12)))) { 174 if (!ipiInterrupting[i]) 175 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ3, 0); 176 ipiInterrupting[i]++; 177 DPRINTF(IPI, "send cpu=%d pending=%d from=%d\n", i, 178 ipiInterrupting[i], req->cpu_num); 179 } 180 } 181 supportedWrite = true; 182 } 183 //If it is bits 8-11, then clearing IPI's 184 uint64_t ipintr; 185 if ((ipintr = (*(uint64_t*) data) & (0xf << 8))) { 186 //Clear the bits in IPINTR 187 misc &= ~(ipintr); 188 for (int i=0; i < 4; i++) { 189 if ((ipintr & (1 << (i + 8))) && ipiInterrupting[i]) { 190 if (!(--ipiInterrupting[i])) 191 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ3, 0); 192 DPRINTF(IPI, "clearing cpu=%d pending=%d from=%d\n", i, 193 ipiInterrupting[i] + 1, req->cpu_num); 194 } 195 } 196 supportedWrite = true; 197 } 198 if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n"); 199 return No_Fault; 200 case TSDEV_CC_AAR0: 201 case TSDEV_CC_AAR1: 202 case TSDEV_CC_AAR2: 203 case TSDEV_CC_AAR3: 204 panic("TSDEV_CC_AARx write not implemeted\n"); 205 return No_Fault; 206 case TSDEV_CC_DIM0: 207 case TSDEV_CC_DIM1: 208 case TSDEV_CC_DIM2: 209 case TSDEV_CC_DIM3: 210 int number; 211 if(daddr == TSDEV_CC_DIM0) 212 number = 0; 213 else if(daddr == TSDEV_CC_DIM1) 214 number = 1; 215 else if(daddr == TSDEV_CC_DIM2) 216 number = 2; 217 else 218 number = 3; 219 220 uint64_t bitvector; 221 uint64_t olddim; 222 uint64_t olddir; 223 224 olddim = dim[number]; 225 olddir = dir[number]; 226 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::postDRIR(uint32_t interrupt) 293{ 294 uint64_t bitvector = (uint64_t)0x1 << interrupt; 295 drir |= bitvector; 296 for(int i=0; i < Tsunami::Max_CPUs; i++) { 297 dir[i] = dim[i] & drir; 298 if (dim[i] & bitvector) { 299 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt); 300 DPRINTF(Tsunami, "posting dir interrupt to cpu %d," 301 "interrupt %d\n",i, interrupt); 302 } 303 } 304} 305 306void 307TsunamiCChip::clearDRIR(uint32_t interrupt) 308{ 309 uint64_t bitvector = (uint64_t)0x1 << interrupt; 310 if (drir & bitvector) 311 { 312 drir &= ~bitvector; 313 for(int i=0; i < Tsunami::Max_CPUs; i++) { 314 if (dir[i] & bitvector) { 315 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt); 316 DPRINTF(Tsunami, "clearing dir interrupt to cpu %d," 317 "interrupt %d\n",i, interrupt); 318 319 } 320 dir[i] = dim[i] & drir; 321 } 322 } 323 else 324 DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt); 325} 326 327void 328TsunamiCChip::serialize(std::ostream &os) 329{ 330 SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); 331 SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); 332 SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); 333 SERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs); 334 SERIALIZE_SCALAR(drir); 335 SERIALIZE_SCALAR(misc); 336 SERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs); 337} 338 339void 340TsunamiCChip::unserialize(Checkpoint *cp, const std::string §ion) 341{ 342 UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); 343 UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); 344 UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); 345 UNSERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs); 346 UNSERIALIZE_SCALAR(drir); 347 UNSERIALIZE_SCALAR(misc); 348 UNSERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs); 349} 350 351BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) 352 353 SimObjectParam<Tsunami *> tsunami; 354 SimObjectParam<MemoryController *> mmu; 355 Param<Addr> addr; 356 357END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) 358 359BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) 360 361 INIT_PARAM(tsunami, "Tsunami"), 362 INIT_PARAM(mmu, "Memory Controller"), 363 INIT_PARAM(addr, "Device Address") 364 365END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) 366 367CREATE_SIM_OBJECT(TsunamiCChip) 368{ 369 return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu); 370} 371 372REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip) 373