tsunami_cchip.cc revision 817
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 } 35 36 drir = 0; 37 misc = 0; 38 RTCInterrupting = false; 39 40 //Put back pointer in tsunami 41 tsunami->cchip = this; 42} 43 44Fault 45TsunamiCChip::read(MemReqPtr &req, uint8_t *data) 46{ 47 DPRINTF(Tsunami, "read va=%#x size=%d\n", 48 req->vaddr, req->size); 49 50 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 51 ExecContext *xc = req->xc; 52 53 switch (req->size) { 54 55 case sizeof(uint64_t): 56 switch(daddr) { 57 case TSDEV_CC_CSR: 58 *(uint64_t*)data = 0x0; 59 return No_Fault; 60 case TSDEV_CC_MTR: 61 panic("TSDEV_CC_MTR not implemeted\n"); 62 return No_Fault; 63 case TSDEV_CC_MISC: 64 *(uint64_t*)data = misc | (xc->cpu_id & 0x3); 65 return No_Fault; 66 case TSDEV_CC_AAR0: 67 case TSDEV_CC_AAR1: 68 case TSDEV_CC_AAR2: 69 case TSDEV_CC_AAR3: 70 panic("TSDEV_CC_AARx not implemeted\n"); 71 return No_Fault; 72 case TSDEV_CC_DIM0: 73 *(uint64_t*)data = dim[0]; 74 return No_Fault; 75 case TSDEV_CC_DIM1: 76 *(uint64_t*)data = dim[1]; 77 return No_Fault; 78 case TSDEV_CC_DIM2: 79 *(uint64_t*)data = dim[2]; 80 return No_Fault; 81 case TSDEV_CC_DIM3: 82 *(uint64_t*)data = dim[3]; 83 return No_Fault; 84 case TSDEV_CC_DIR0: 85 *(uint64_t*)data = dir[0]; 86 return No_Fault; 87 case TSDEV_CC_DIR1: 88 *(uint64_t*)data = dir[1]; 89 return No_Fault; 90 case TSDEV_CC_DIR2: 91 *(uint64_t*)data = dir[2]; 92 return No_Fault; 93 case TSDEV_CC_DIR3: 94 *(uint64_t*)data = dir[3]; 95 return No_Fault; 96 case TSDEV_CC_DRIR: 97 *(uint64_t*)data = drir; 98 return No_Fault; 99 case TSDEV_CC_PRBEN: 100 panic("TSDEV_CC_PRBEN not implemented\n"); 101 return No_Fault; 102 case TSDEV_CC_IIC0: 103 case TSDEV_CC_IIC1: 104 case TSDEV_CC_IIC2: 105 case TSDEV_CC_IIC3: 106 panic("TSDEV_CC_IICx not implemented\n"); 107 return No_Fault; 108 case TSDEV_CC_MPR0: 109 case TSDEV_CC_MPR1: 110 case TSDEV_CC_MPR2: 111 case TSDEV_CC_MPR3: 112 panic("TSDEV_CC_MPRx not implemented\n"); 113 return No_Fault; 114 default: 115 panic("default in cchip read reached, accessing 0x%x\n"); 116 } // uint64_t 117 118 break; 119 case sizeof(uint32_t): 120 case sizeof(uint16_t): 121 case sizeof(uint8_t): 122 default: 123 panic("invalid access size(?) for tsunami register!\n"); 124 } 125 DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); 126 127 return No_Fault; 128} 129 130Fault 131TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) 132{ 133 DPRINTF(Tsunami, "write - va=%#x size=%d \n", 134 req->vaddr, req->size); 135 136 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 137 uint64_t olddim; 138 139 switch (req->size) { 140 141 case sizeof(uint64_t): 142 switch(daddr) { 143 case TSDEV_CC_CSR: 144 panic("TSDEV_CC_CSR write\n"); 145 return No_Fault; 146 case TSDEV_CC_MTR: 147 panic("TSDEV_CC_MTR write not implemented\n"); 148 return No_Fault; 149 case TSDEV_CC_MISC: 150 //If it is the seventh bit, clear the RTC interrupt 151 if ((*(uint64_t*) data) & (1<<4)) { 152 RTCInterrupting = false; 153 tsunami->intrctrl->clear(0, TheISA::INTLEVEL_IRQ2, 0); 154 DPRINTF(Tsunami, "clearing rtc interrupt\n"); 155 misc &= ~(1<<4); 156 } else panic("TSDEV_CC_MISC write not implemented\n"); 157 return No_Fault; 158 case TSDEV_CC_AAR0: 159 case TSDEV_CC_AAR1: 160 case TSDEV_CC_AAR2: 161 case TSDEV_CC_AAR3: 162 panic("TSDEV_CC_AARx write not implemeted\n"); 163 return No_Fault; 164 case TSDEV_CC_DIM0: 165 case TSDEV_CC_DIM1: 166 case TSDEV_CC_DIM2: 167 case TSDEV_CC_DIM3: 168 int number; 169 if(daddr == TSDEV_CC_DIM0) 170 number = 0; 171 else if(daddr == TSDEV_CC_DIM1) 172 number = 1; 173 else if(daddr == TSDEV_CC_DIM2) 174 number = 2; 175 else 176 number = 3; 177 178 olddim = dim[number]; 179 dim[number] = *(uint64_t*)data; 180 dir[number] = dim[number] & drir; 181 uint64_t bitvector; 182 for(int x = 0; x < 64; x++) 183 { 184 bitvector = 1 << x; 185 // Figure out which bits have changed 186 if ((dim[number] & bitvector) != (olddim & bitvector)) 187 { 188 // The bit is now set and it wasn't before (set) 189 if((dim[number] & bitvector) && (dir[number] & bitvector)) 190 { 191 tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x); 192 DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n"); 193 } 194 else if (!(dir[number] & bitvector)) 195 { 196 // The bit was set and now its now clear and 197 // we were interrupting on that bit before 198 tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x); 199 DPRINTF(Tsunami, "dim write resulting in clear" 200 "dir interrupt to cpu 0\n"); 201 202 } 203 204 205 } 206 } 207 return No_Fault; 208 case TSDEV_CC_DIR0: 209 case TSDEV_CC_DIR1: 210 case TSDEV_CC_DIR2: 211 case TSDEV_CC_DIR3: 212 panic("TSDEV_CC_DIR write not implemented\n"); 213 case TSDEV_CC_DRIR: 214 panic("TSDEV_CC_DRIR write not implemented\n"); 215 case TSDEV_CC_PRBEN: 216 panic("TSDEV_CC_PRBEN write not implemented\n"); 217 case TSDEV_CC_IIC0: 218 case TSDEV_CC_IIC1: 219 case TSDEV_CC_IIC2: 220 case TSDEV_CC_IIC3: 221 panic("TSDEV_CC_IICx write not implemented\n"); 222 case TSDEV_CC_MPR0: 223 case TSDEV_CC_MPR1: 224 case TSDEV_CC_MPR2: 225 case TSDEV_CC_MPR3: 226 panic("TSDEV_CC_MPRx write not implemented\n"); 227 default: 228 panic("default in cchip read reached, accessing 0x%x\n"); 229 } 230 231 break; 232 case sizeof(uint32_t): 233 case sizeof(uint16_t): 234 case sizeof(uint8_t): 235 default: 236 panic("invalid access size(?) for tsunami register!\n"); 237 } 238 239 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); 240 241 return No_Fault; 242} 243 244void 245TsunamiCChip::postDRIR(uint32_t interrupt) 246{ 247 uint64_t bitvector = 0x1 << interrupt; 248 drir |= bitvector; 249 for(int i=0; i < Tsunami::Max_CPUs; i++) { 250 dir[i] = dim[i] & drir; 251 if (dim[i] & bitvector) { 252 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt); 253 DPRINTF(Tsunami, "posting dir interrupt to cpu %d," 254 "interrupt %d\n",i, interrupt); 255 } 256 } 257} 258 259void 260TsunamiCChip::clearDRIR(uint32_t interrupt) 261{ 262 uint64_t bitvector = 0x1 << interrupt; 263 if (drir & bitvector) 264 { 265 drir &= ~bitvector; 266 for(int i=0; i < Tsunami::Max_CPUs; i++) { 267 if (dir[i] & bitvector) { 268 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt); 269 DPRINTF(Tsunami, "clearing dir interrupt to cpu %d," 270 "interrupt %d\n",i, interrupt); 271 272 } 273 dir[i] = dim[i] & drir; 274 } 275 } 276 else 277 DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt); 278} 279 280void 281TsunamiCChip::serialize(std::ostream &os) 282{ 283 SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); 284 SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); 285 SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); 286 SERIALIZE_SCALAR(drir); 287 SERIALIZE_SCALAR(misc); 288 SERIALIZE_SCALAR(RTCInterrupting); 289} 290 291void 292TsunamiCChip::unserialize(Checkpoint *cp, const std::string §ion) 293{ 294 UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); 295 UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); 296 UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); 297 UNSERIALIZE_SCALAR(drir); 298 UNSERIALIZE_SCALAR(misc); 299 UNSERIALIZE_SCALAR(RTCInterrupting); 300} 301 302BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) 303 304 SimObjectParam<Tsunami *> tsunami; 305 SimObjectParam<MemoryController *> mmu; 306 Param<Addr> addr; 307 308END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) 309 310BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) 311 312 INIT_PARAM(tsunami, "Tsunami"), 313 INIT_PARAM(mmu, "Memory Controller"), 314 INIT_PARAM(addr, "Device Address") 315 316END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) 317 318CREATE_SIM_OBJECT(TsunamiCChip) 319{ 320 return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu); 321} 322 323REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip) 324