iob.cc revision 4104
112SN/A/* 210037SARM gem5 Developers * Copyright (c) 2006 The Regents of The University of Michigan 310037SARM gem5 Developers * All rights reserved. 410037SARM gem5 Developers * 510037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without 610037SARM gem5 Developers * modification, are permitted provided that the following conditions are 710037SARM gem5 Developers * met: redistributions of source code must retain the above copyright 810037SARM gem5 Developers * notice, this list of conditions and the following disclaimer; 910037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright 1010037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the 1110037SARM gem5 Developers * documentation and/or other materials provided with the distribution; 1210037SARM gem5 Developers * neither the name of the copyright holders nor the names of its 1310037SARM gem5 Developers * contributors may be used to endorse or promote products derived from 141762SN/A * this software without specific prior written permission. 1512SN/A * 1612SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712SN/A * 2812SN/A * Authors: Ali Saidi 2912SN/A */ 3012SN/A 3112SN/A/** @file 3212SN/A * This device implemetns the niagara I/O bridge chip. It manages incomming 3312SN/A * interrupts and posts them to the CPU when needed. It holds mask registers and 3412SN/A * various status registers for CPUs to check what interrupts are pending as 3512SN/A * well as facilities to send IPIs to other cpus. 3612SN/A */ 3712SN/A 3812SN/A#include <cstring> 392665Ssaidi@eecs.umich.edu 402665Ssaidi@eecs.umich.edu#include "arch/sparc/isa_traits.hh" 4112SN/A#include "base/trace.hh" 4212SN/A#include "cpu/intr_control.hh" 4312SN/A#include "dev/sparc/iob.hh" 4412SN/A#include "dev/platform.hh" 4512SN/A#include "mem/port.hh" 465070Ssaidi@eecs.umich.edu#include "mem/packet_access.hh" 475090Sgblack@eecs.umich.edu#include "sim/builder.hh" 4812SN/A#include "sim/system.hh" 498229Snate@binkert.org 508229Snate@binkert.orgIob::Iob(Params *p) 5112SN/A : PioDevice(p), ic(p->platform->intrctrl) 5212SN/A{ 5312SN/A iobManAddr = ULL(0x9800000000); 5412SN/A iobManSize = ULL(0x0100000000); 555090Sgblack@eecs.umich.edu iobJBusAddr = ULL(0x9F00000000); 565090Sgblack@eecs.umich.edu iobJBusSize = ULL(0x0100000000); 575090Sgblack@eecs.umich.edu assert (params()->system->threadContexts.size() <= MaxNiagaraProcs); 582976Sgblack@eecs.umich.edu // Get the interrupt controller from the platform 592976Sgblack@eecs.umich.edu ic = platform->intrctrl; 602976Sgblack@eecs.umich.edu 612976Sgblack@eecs.umich.edu for (int x = 0; x < NumDeviceIds; ++x) { 622976Sgblack@eecs.umich.edu intMan[x].cpu = 0; 635070Ssaidi@eecs.umich.edu intMan[x].vector = 0; 642976Sgblack@eecs.umich.edu intCtl[x].mask = true; 65468SN/A intCtl[x].pend = false; 667581SAli.Saidi@arm.com } 67468SN/A 6810880SCurtis.Dunham@arm.com} 69360SN/A 7012SN/ATick 715070Ssaidi@eecs.umich.eduIob::read(PacketPtr pkt) 725070Ssaidi@eecs.umich.edu{ 735070Ssaidi@eecs.umich.edu assert(pkt->result == Packet::Unknown); 745090Sgblack@eecs.umich.edu 755090Sgblack@eecs.umich.edu if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize) 7612SN/A readIob(pkt); 7712SN/A else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize) 7812SN/A readJBus(pkt); 798852Sandreas.hansson@arm.com else 8010037SARM gem5 Developers panic("Invalid address reached Iob\n"); 8110037SARM gem5 Developers 823812Ssaidi@eecs.umich.edu pkt->result = Packet::Success; 833812Ssaidi@eecs.umich.edu return pioDelay; 843812Ssaidi@eecs.umich.edu} 853812Ssaidi@eecs.umich.edu 869641Sguodeyuan@tsinghua.org.cnvoid 879641Sguodeyuan@tsinghua.org.cnIob::readIob(PacketPtr pkt) 8812SN/A{ 895070Ssaidi@eecs.umich.edu Addr accessAddr = pkt->getAddr() - iobManAddr; 905070Ssaidi@eecs.umich.edu int index; 913917Ssaidi@eecs.umich.edu uint64_t data; 9210880SCurtis.Dunham@arm.com 9312SN/A if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) { 942976Sgblack@eecs.umich.edu index = (accessAddr - IntManAddr) >> 3; 952976Sgblack@eecs.umich.edu data = intMan[index].cpu << 8 | intMan[index].vector << 0; 962976Sgblack@eecs.umich.edu pkt->set(data); 9712SN/A return; 9812SN/A } 9912SN/A 100 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) { 101 index = (accessAddr - IntManAddr) >> 3; 102 data = intCtl[index].mask ? 1 << 2 : 0 | 103 intCtl[index].pend ? 1 << 0 : 0; 104 pkt->set(data); 105 return; 106 } 107 108 if (accessAddr == JIntVecAddr) { 109 pkt->set(jIntVec); 110 return; 111 } 112 113 panic("Read to unknown IOB offset 0x%x\n", accessAddr); 114} 115 116void 117Iob::readJBus(PacketPtr pkt) 118{ 119 Addr accessAddr = pkt->getAddr() - iobJBusAddr; 120 int cpuid = pkt->req->getCpuNum(); 121 int index; 122 uint64_t data; 123 124 125 126 127 if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) { 128 index = (accessAddr - JIntData0Addr) >> 3; 129 pkt->set(jBusData0[index]); 130 return; 131 } 132 133 if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) { 134 index = (accessAddr - JIntData1Addr) >> 3; 135 pkt->set(jBusData1[index]); 136 return; 137 } 138 139 if (accessAddr == JIntDataA0Addr) { 140 pkt->set(jBusData0[cpuid]); 141 return; 142 } 143 144 if (accessAddr == JIntDataA1Addr) { 145 pkt->set(jBusData1[cpuid]); 146 return; 147 } 148 149 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) { 150 index = (accessAddr - JIntBusyAddr) >> 3; 151 data = jIntBusy[index].busy ? 1 << 5 : 0 | 152 jIntBusy[index].source; 153 pkt->set(data); 154 return; 155 } 156 if (accessAddr == JIntABusyAddr) { 157 data = jIntBusy[cpuid].busy ? 1 << 5 : 0 | 158 jIntBusy[cpuid].source; 159 pkt->set(data); 160 return; 161 }; 162 163 panic("Read to unknown JBus offset 0x%x\n", accessAddr); 164} 165 166Tick 167Iob::write(PacketPtr pkt) 168{ 169 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize) 170 writeIob(pkt); 171 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize) 172 writeJBus(pkt); 173 else 174 panic("Invalid address reached Iob\n"); 175 176 177 pkt->result = Packet::Success; 178 return pioDelay; 179} 180 181void 182Iob::writeIob(PacketPtr pkt) 183{ 184 Addr accessAddr = pkt->getAddr() - iobManAddr; 185 int index; 186 uint64_t data; 187 188 if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) { 189 index = (accessAddr - IntManAddr) >> 3; 190 data = pkt->get<uint64_t>(); 191 intMan[index].cpu = bits(data,12,8); 192 intMan[index].vector = bits(data,5,0); 193 return; 194 } 195 196 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) { 197 index = (accessAddr - IntManAddr) >> 3; 198 data = pkt->get<uint64_t>(); 199 intCtl[index].mask = bits(data,2,2); 200 if (bits(data,1,1)) 201 intCtl[index].pend = false; 202 return; 203 } 204 205 if (accessAddr == JIntVecAddr) { 206 jIntVec = bits(pkt->get<uint64_t>(), 5,0); 207 return; 208 } 209 210 if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) { 211 Type type; 212 int cpu_id; 213 int vector; 214 index = (accessAddr - IntManAddr) >> 3; 215 data = pkt->get<uint64_t>(); 216 type = (Type)bits(data,17,16); 217 cpu_id = bits(data, 12,8); 218 vector = bits(data,5,0); 219 generateIpi(type,cpu_id, vector); 220 return; 221 } 222 223 panic("Write to unknown IOB offset 0x%x\n", accessAddr); 224} 225 226void 227Iob::writeJBus(PacketPtr pkt) 228{ 229 Addr accessAddr = pkt->getAddr() - iobJBusAddr; 230 int cpuid = pkt->req->getCpuNum(); 231 int index; 232 uint64_t data; 233 234 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) { 235 index = (accessAddr - JIntBusyAddr) >> 3; 236 data = pkt->get<uint64_t>(); 237 jIntBusy[index].busy = bits(data,5,5); 238 return; 239 } 240 if (accessAddr == JIntABusyAddr) { 241 data = pkt->get<uint64_t>(); 242 jIntBusy[cpuid].busy = bits(data,5,5); 243 return; 244 }; 245 246 panic("Write to unknown JBus offset 0x%x\n", accessAddr); 247} 248 249void 250Iob::receiveDeviceInterrupt(DeviceId devid) 251{ 252 assert(devid < NumDeviceIds); 253 if (intCtl[devid].mask) 254 return; 255 intCtl[devid].mask = true; 256 intCtl[devid].pend = true; 257 ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector); 258} 259 260 261void 262Iob::generateIpi(Type type, int cpu_id, int vector) 263{ 264 // Only handle interrupts for the moment... Cpu Idle/reset/resume will be 265 // later 266 if (type != 0) { 267 warn("Ignoring IntVecDis write\n"); 268 return; 269 } 270 assert(type == 0); 271 ic->post(cpu_id, SparcISA::IT_INT_VEC, vector); 272} 273 274bool 275Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1) 276{ 277 // If we are already dealing with an interrupt for that cpu we can't deal 278 // with another one right now... come back later 279 if (jIntBusy[cpu_id].busy) 280 return false; 281 282 jIntBusy[cpu_id].busy = true; 283 jIntBusy[cpu_id].source = source; 284 jBusData0[cpu_id] = d0; 285 jBusData1[cpu_id] = d1; 286 287 ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec); 288 return true; 289} 290 291void 292Iob::addressRanges(AddrRangeList &range_list) 293{ 294 range_list.clear(); 295 range_list.push_back(RangeSize(iobManAddr, iobManSize)); 296 range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize)); 297} 298 299 300void 301Iob::serialize(std::ostream &os) 302{ 303 304 SERIALIZE_SCALAR(jIntVec); 305 SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs); 306 SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs); 307 for (int x = 0; x < NumDeviceIds; x++) { 308 nameOut(os, csprintf("%s.Int%d", name(), x)); 309 paramOut(os, "cpu", intMan[x].cpu); 310 paramOut(os, "vector", intMan[x].vector); 311 paramOut(os, "mask", intCtl[x].mask); 312 paramOut(os, "pend", intCtl[x].pend); 313 }; 314 for (int x = 0; x < MaxNiagaraProcs; x++) { 315 nameOut(os, csprintf("%s.jIntBusy%d", name(), x)); 316 paramOut(os, "busy", jIntBusy[x].busy); 317 paramOut(os, "source", jIntBusy[x].source); 318 }; 319} 320 321void 322Iob::unserialize(Checkpoint *cp, const std::string §ion) 323{ 324 UNSERIALIZE_SCALAR(jIntVec); 325 UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs); 326 UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs); 327 for (int x = 0; x < NumDeviceIds; x++) { 328 paramIn(cp, csprintf("%s.Int%d", name(), x), "cpu", intMan[x].cpu); 329 paramIn(cp, csprintf("%s.Int%d", name(), x), "vector", intMan[x].vector); 330 paramIn(cp, csprintf("%s.Int%d", name(), x), "mask", intCtl[x].mask); 331 paramIn(cp, csprintf("%s.Int%d", name(), x), "pend", intCtl[x].pend); 332 }; 333 for (int x = 0; x < MaxNiagaraProcs; x++) { 334 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "busy", jIntBusy[x].busy); 335 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "source", jIntBusy[x].source); 336 }; 337} 338 339 340 341 342BEGIN_DECLARE_SIM_OBJECT_PARAMS(Iob) 343 Param<Tick> pio_latency; 344 SimObjectParam<Platform *> platform; 345 SimObjectParam<System *> system; 346END_DECLARE_SIM_OBJECT_PARAMS(Iob) 347 348BEGIN_INIT_SIM_OBJECT_PARAMS(Iob) 349 350 INIT_PARAM(pio_latency, "Programmed IO latency"), 351 INIT_PARAM(platform, "platform"), 352 INIT_PARAM(system, "system object") 353 354END_INIT_SIM_OBJECT_PARAMS(Iob) 355 356CREATE_SIM_OBJECT(Iob) 357{ 358 Iob::Params *p = new Iob::Params; 359 p->name = getInstanceName(); 360 p->pio_delay = pio_latency; 361 p->platform = platform; 362 p->system = system; 363 return new Iob(p); 364} 365 366REGISTER_SIM_OBJECT("Iob", Iob) 367