X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=dev%2Ftsunami_cchip.cc;h=870924a2fff133ab5307c6bdd8fe21ceef2262fd;hb=f1f85c5470c67adc5071296c53e69abb0b47b09c;hp=cdef6202ed8bc5e67425fbddd35021f990341f10;hpb=0f34a00703bf4dd2cd0ff673e343b72ad5bdc5bd;p=gem5.git diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc index cdef6202e..870924a2f 100644 --- a/dev/tsunami_cchip.cc +++ b/dev/tsunami_cchip.cc @@ -1,4 +1,30 @@ -/* $Id$ */ +/* + * Copyright (c) 2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ /* @file * Emulation of the Tsunami CChip CSRs @@ -9,21 +35,23 @@ #include #include "base/trace.hh" -#include "cpu/exec_context.hh" -#include "dev/console.hh" #include "dev/tsunami_cchip.hh" #include "dev/tsunamireg.h" #include "dev/tsunami.hh" -#include "cpu/intr_control.hh" +#include "mem/bus/bus.hh" +#include "mem/bus/pio_interface.hh" +#include "mem/bus/pio_interface_impl.hh" #include "mem/functional_mem/memory_control.hh" +#include "cpu/intr_control.hh" #include "sim/builder.hh" #include "sim/system.hh" using namespace std; TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, - MemoryController *mmu) - : FunctionalMemory(name), addr(a), tsunami(t) + MemoryController *mmu, HierParams *hier, Bus* bus, + Tick pio_latency) + : PioDevice(name), addr(a), tsunami(t) { mmu->add_child(this, Range(addr, addr + size)); @@ -31,11 +59,19 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, dim[i] = 0; dir[i] = 0; dirInterrupting[i] = false; + ipiInterrupting[i] = false; + RTCInterrupting[i] = false; + } + + if (bus) { + pioInterface = newPioInterface(name, hier, bus, this, + &TsunamiCChip::cacheAccess); + pioInterface->addAddrRange(addr, addr + size - 1); + pioLatency = pio_latency * bus->clockRatio; } drir = 0; misc = 0; - RTCInterrupting = false; //Put back pointer in tsunami tsunami->cchip = this; @@ -47,7 +83,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data) DPRINTF(Tsunami, "read va=%#x size=%d\n", req->vaddr, req->size); - Addr daddr = (req->paddr & size) >> 6; + Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; ExecContext *xc = req->xc; switch (req->size) { @@ -67,7 +103,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data) case TSDEV_CC_AAR1: case TSDEV_CC_AAR2: case TSDEV_CC_AAR3: - panic("TSDEV_CC_AARx not implemeted\n"); + *(uint64_t*)data = 0; return No_Fault; case TSDEV_CC_DIM0: *(uint64_t*)data = dim[0]; @@ -130,30 +166,77 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data) Fault TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) { - DPRINTF(Tsunami, "write - va=%#x size=%d \n", - req->vaddr, req->size); + DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n", + req->vaddr, *(uint64_t*)data, req->size); + + Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; - Addr daddr = (req->paddr & size) >> 6; + bool supportedWrite = false; + uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); switch (req->size) { case sizeof(uint64_t): switch(daddr) { - case TSDEV_CC_CSR: + case TSDEV_CC_CSR: panic("TSDEV_CC_CSR write\n"); return No_Fault; case TSDEV_CC_MTR: panic("TSDEV_CC_MTR write not implemented\n"); return No_Fault; case TSDEV_CC_MISC: - //If it is the seventh bit, clear the RTC interrupt - if ((*(uint64_t*) data) & (1<<4)) { - RTCInterrupting = false; - tsunami->intrctrl->clear(0, TheISA::INTLEVEL_IRQ2, 0); - DPRINTF(Tsunami, "clearing rtc interrupt\n"); - misc &= ~(1<<4); - } else panic("TSDEV_CC_MISC write not implemented\n"); - return No_Fault; + //If it is the 4-7th bit, clear the RTC interrupt + uint64_t itintr; + if ((itintr = (*(uint64_t*) data) & (0xf<<4))) { + //Clear the bits in ITINTR + misc &= ~(itintr); + for (int i=0; i < size; i++) { + if ((itintr & (1 << (i+4))) && RTCInterrupting[i]) { + tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0); + RTCInterrupting[i] = false; + DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i); + } + } + supportedWrite = true; + } + //If it is 12th-15th bit, IPI sent to Processor 1 + uint64_t ipreq; + if ((ipreq = (*(uint64_t*) data) & (0xf << 12))) { + //Set the bits in IPINTR + misc |= (ipreq >> 4); + for (int i=0; i < size; i++) { + if ((ipreq & (1 << (i + 12)))) { + if (!ipiInterrupting[i]) + tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ3, 0); + ipiInterrupting[i]++; + DPRINTF(IPI, "send cpu=%d pending=%d from=%d\n", i, + ipiInterrupting[i], req->cpu_num); + } + } + supportedWrite = true; + } + //If it is bits 8-11, then clearing IPI's + uint64_t ipintr; + if ((ipintr = (*(uint64_t*) data) & (0xf << 8))) { + //Clear the bits in IPINTR + misc &= ~(ipintr); + for (int i=0; i < size; i++) { + if ((ipintr & (1 << (i + 8))) && ipiInterrupting[i]) { + if (!(--ipiInterrupting[i])) + tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ3, 0); + DPRINTF(IPI, "clearing cpu=%d pending=%d from=%d\n", i, + ipiInterrupting[i] + 1, req->cpu_num); + } + } + supportedWrite = true; + } + + // ignore NXMs + if (*(uint64_t*)data & 0x10000000) + supportedWrite = true; + + if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n"); + return No_Fault; case TSDEV_CC_AAR0: case TSDEV_CC_AAR1: case TSDEV_CC_AAR2: @@ -161,47 +244,52 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) panic("TSDEV_CC_AARx write not implemeted\n"); return No_Fault; case TSDEV_CC_DIM0: - dim[0] = *(uint64_t*)data; - if (dim[0] & drir) { - dir[0] = dim[0] & drir; - if (!dirInterrupting[0]) { - dirInterrupting[0] = true; - tsunami->intrctrl->post(0, TheISA::INTLEVEL_IRQ1, 0); - DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n"); - } - } - return No_Fault; case TSDEV_CC_DIM1: - dim[1] = *(uint64_t*)data; - if (dim[1] & drir) { - dir[1] = dim[1] & drir; - if (!dirInterrupting[1]) { - dirInterrupting[1] = true; - tsunami->intrctrl->post(1, TheISA::INTLEVEL_IRQ1, 0); - DPRINTF(Tsunami, "posting dir interrupt to cpu 1\n"); - } - } - return No_Fault; case TSDEV_CC_DIM2: - dim[2] = *(uint64_t*)data; - if (dim[2] & drir) { - dir[2] = dim[2] & drir; - if (!dirInterrupting[2]) { - dirInterrupting[2] = true; - tsunami->intrctrl->post(2, TheISA::INTLEVEL_IRQ1, 0); - DPRINTF(Tsunami, "posting dir interrupt to cpu 2\n"); - } - } - return No_Fault; case TSDEV_CC_DIM3: - dim[3] = *(uint64_t*)data; - if ((dim[3] & drir) /*And Not Already Int*/) { - dir[3] = dim[3] & drir; - if (!dirInterrupting[3]) { - dirInterrupting[3] = true; - tsunami->intrctrl->post(3, TheISA::INTLEVEL_IRQ1, 0); - DPRINTF(Tsunami, "posting dir interrupt to cpu 3\n"); - } + int number; + if(daddr == TSDEV_CC_DIM0) + number = 0; + else if(daddr == TSDEV_CC_DIM1) + number = 1; + else if(daddr == TSDEV_CC_DIM2) + number = 2; + else + number = 3; + + uint64_t bitvector; + uint64_t olddim; + uint64_t olddir; + + olddim = dim[number]; + olddir = dir[number]; + dim[number] = *(uint64_t*)data; + dir[number] = dim[number] & drir; + for(int x = 0; x < 64; x++) + { + bitvector = (uint64_t)1 << x; + // Figure out which bits have changed + if ((dim[number] & bitvector) != (olddim & bitvector)) + { + // The bit is now set and it wasn't before (set) + if((dim[number] & bitvector) && (dir[number] & bitvector)) + { + tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x); + DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n"); + } + else if ((olddir & bitvector) && + !(dir[number] & bitvector)) + { + // The bit was set and now its now clear and + // we were interrupting on that bit before + tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x); + DPRINTF(Tsunami, "dim write resulting in clear" + "dir interrupt to cpu 0\n"); + + } + + + } } return No_Fault; case TSDEV_CC_DIR0: @@ -209,25 +297,20 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) case TSDEV_CC_DIR2: case TSDEV_CC_DIR3: panic("TSDEV_CC_DIR write not implemented\n"); - return No_Fault; case TSDEV_CC_DRIR: panic("TSDEV_CC_DRIR write not implemented\n"); - return No_Fault; case TSDEV_CC_PRBEN: panic("TSDEV_CC_PRBEN write not implemented\n"); - return No_Fault; case TSDEV_CC_IIC0: case TSDEV_CC_IIC1: case TSDEV_CC_IIC2: case TSDEV_CC_IIC3: panic("TSDEV_CC_IICx write not implemented\n"); - return No_Fault; case TSDEV_CC_MPR0: case TSDEV_CC_MPR1: case TSDEV_CC_MPR2: case TSDEV_CC_MPR3: panic("TSDEV_CC_MPRx write not implemented\n"); - return No_Fault; default: panic("default in cchip read reached, accessing 0x%x\n"); } @@ -246,45 +329,76 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) } void -TsunamiCChip::postDRIR(uint64_t bitvector) +TsunamiCChip::postRTC() +{ + int size = tsunami->intrctrl->cpu->system->execContexts.size(); + + for (int i = 0; i < size; i++) { + if (!RTCInterrupting[i]) { + misc |= 16 << i; + RTCInterrupting[i] = true; + tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0); + DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i); + } + } + +} + +void +TsunamiCChip::postDRIR(uint32_t interrupt) { + uint64_t bitvector = (uint64_t)0x1 << interrupt; drir |= bitvector; - for(int i=0; i < Tsunami::Max_CPUs; i++) { - if (bitvector & dim[i]) { - dir[i] |= bitvector; - if (!dirInterrupting[i]) { - dirInterrupting[i] = true; - tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, 0); - DPRINTF(Tsunami, "posting dir interrupt to cpu %d\n",i); - } + uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); + for(int i=0; i < size; i++) { + dir[i] = dim[i] & drir; + if (dim[i] & bitvector) { + tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt); + DPRINTF(Tsunami, "posting dir interrupt to cpu %d," + "interrupt %d\n",i, interrupt); } } } void -TsunamiCChip::clearDRIR(uint64_t bitvector) +TsunamiCChip::clearDRIR(uint32_t interrupt) { - drir &= ~bitvector; - for(int i=0; i < Tsunami::Max_CPUs; i++) { - dir[i] &= ~bitvector; - if (!dir[i]) { - dirInterrupting[i] = false; - tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, 0); - DPRINTF(Tsunami, "clearing dir interrupt to cpu %d\n", i); + uint64_t bitvector = (uint64_t)0x1 << interrupt; + uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); + if (drir & bitvector) + { + drir &= ~bitvector; + for(int i=0; i < size; i++) { + if (dir[i] & bitvector) { + tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt); + DPRINTF(Tsunami, "clearing dir interrupt to cpu %d," + "interrupt %d\n",i, interrupt); + } + dir[i] = dim[i] & drir; } } + else + DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt); } +Tick +TsunamiCChip::cacheAccess(MemReqPtr &req) +{ + return curTick + pioLatency; +} + + void TsunamiCChip::serialize(std::ostream &os) { SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); + SERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs); SERIALIZE_SCALAR(drir); SERIALIZE_SCALAR(misc); - SERIALIZE_SCALAR(RTCInterrupting); + SERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs); } void @@ -293,9 +407,10 @@ TsunamiCChip::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); + UNSERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs); UNSERIALIZE_SCALAR(drir); UNSERIALIZE_SCALAR(misc); - UNSERIALIZE_SCALAR(RTCInterrupting); + UNSERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs); } BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) @@ -303,6 +418,9 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) SimObjectParam tsunami; SimObjectParam mmu; Param addr; + SimObjectParam io_bus; + Param pio_latency; + SimObjectParam hier; END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) @@ -310,13 +428,17 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) INIT_PARAM(tsunami, "Tsunami"), INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address") + INIT_PARAM(addr, "Device Address"), + INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), + INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) CREATE_SIM_OBJECT(TsunamiCChip) { - return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu); + return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu, hier, + io_bus, pio_latency); } REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)