Add Iob and remove the fake device

configs/common/FSConfig.py:
    add an attachOnChipIO to force people to think about where "onchip" i/o should be connected in their hierarchy

--HG--
extra : convert_revision : cf79a9a00760b7daf28063f407a04bd38b956843
This commit is contained in:
Ali Saidi 2007-03-03 19:02:31 -05:00
parent 36f43ff6a5
commit 1694c65ba1
4 changed files with 533 additions and 7 deletions

View file

@ -96,6 +96,7 @@ def makeSparcSystem(mem_mode, mdesc = None):
self.membus = Bus(bus_id=1)
self.bridge = Bridge()
self.t1000 = T1000()
self.t1000.attachOnChipIO(self.membus)
self.t1000.attachIO(self.iobus)
self.physmem = PhysicalMemory(range = AddrRange(Addr('1MB'), size = '64MB'), zero = True)
self.physmem2 = PhysicalMemory(range = AddrRange(Addr('2GB'), size ='256MB'), zero = True)

366
src/dev/sparc/iob.cc Normal file
View file

@ -0,0 +1,366 @@
/*
* Copyright (c) 2006 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.
*
* Authors: Ali Saidi
*/
/** @file
* This device implemetns the niagara I/O bridge chip. It manages incomming
* interrupts and posts them to the CPU when needed. It holds mask registers and
* various status registers for CPUs to check what interrupts are pending as
* well as facilities to send IPIs to other cpus.
*/
#include <cstring>
#include "arch/sparc/isa_traits.hh"
#include "base/trace.hh"
#include "cpu/intr_control.hh"
#include "dev/sparc/iob.hh"
#include "dev/platform.hh"
#include "mem/port.hh"
#include "mem/packet_access.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
Iob::Iob(Params *p)
: PioDevice(p), ic(p->platform->intrctrl)
{
iobManAddr = ULL(0x9800000000);
iobManSize = ULL(0x0100000000);
iobJBusAddr = ULL(0x9F00000000);
iobJBusSize = ULL(0x0100000000);
assert (params()->system->threadContexts.size() <= MaxNiagaraProcs);
// Get the interrupt controller from the platform
ic = platform->intrctrl;
for (int x = 0; x < NumDeviceIds; ++x) {
intMan[x].cpu = 0;
intMan[x].vector = 0;
intCtl[x].mask = true;
intCtl[x].pend = false;
}
}
Tick
Iob::read(PacketPtr pkt)
{
assert(pkt->result == Packet::Unknown);
if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
readIob(pkt);
else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
readJBus(pkt);
else
panic("Invalid address reached Iob\n");
pkt->result = Packet::Success;
return pioDelay;
}
void
Iob::readIob(PacketPtr pkt)
{
Addr accessAddr = pkt->getAddr() - iobManAddr;
int index;
uint64_t data;
if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
index = (accessAddr - IntManAddr) >> 3;
data = intMan[index].cpu << 8 | intMan[index].vector << 0;
pkt->set(data);
return;
}
if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
index = (accessAddr - IntManAddr) >> 3;
data = intCtl[index].mask ? 1 << 2 : 0 |
intCtl[index].pend ? 1 << 0 : 0;
pkt->set(data);
return;
}
if (accessAddr == JIntVecAddr) {
pkt->set(jIntVec);
return;
}
panic("Read to unknown IOB offset 0x%x\n", accessAddr);
}
void
Iob::readJBus(PacketPtr pkt)
{
Addr accessAddr = pkt->getAddr() - iobJBusAddr;
int cpuid = pkt->req->getCpuNum();
int index;
uint64_t data;
if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) {
index = (accessAddr - JIntData0Addr) >> 3;
pkt->set(jBusData0[index]);
return;
}
if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) {
index = (accessAddr - JIntData1Addr) >> 3;
pkt->set(jBusData1[index]);
return;
}
if (accessAddr == JIntDataA0Addr) {
pkt->set(jBusData0[cpuid]);
return;
}
if (accessAddr == JIntDataA1Addr) {
pkt->set(jBusData1[cpuid]);
return;
}
if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
index = (accessAddr - JIntBusyAddr) >> 3;
data = jIntBusy[index].busy ? 1 << 5 : 0 |
jIntBusy[index].source;
pkt->set(data);
return;
}
if (accessAddr == JIntABusyAddr) {
data = jIntBusy[cpuid].busy ? 1 << 5 : 0 |
jIntBusy[cpuid].source;
pkt->set(data);
return;
};
panic("Read to unknown JBus offset 0x%x\n", accessAddr);
}
Tick
Iob::write(PacketPtr pkt)
{
if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
writeIob(pkt);
else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
writeJBus(pkt);
else
panic("Invalid address reached Iob\n");
pkt->result = Packet::Success;
return pioDelay;
}
void
Iob::writeIob(PacketPtr pkt)
{
Addr accessAddr = pkt->getAddr() - iobManAddr;
int index;
uint64_t data;
if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
index = (accessAddr - IntManAddr) >> 3;
data = pkt->get<uint64_t>();
intMan[index].cpu = bits(data,12,8);
intMan[index].vector = bits(data,5,0);
return;
}
if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
index = (accessAddr - IntManAddr) >> 3;
data = pkt->get<uint64_t>();
intCtl[index].mask = bits(data,2,2);
if (bits(data,1,1))
intCtl[index].pend = false;
return;
}
if (accessAddr == JIntVecAddr) {
jIntVec = bits(pkt->get<uint64_t>(), 5,0);
return;
}
if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) {
Type type;
int cpu_id;
int vector;
index = (accessAddr - IntManAddr) >> 3;
data = pkt->get<uint64_t>();
type = (Type)bits(data,17,16);
cpu_id = bits(data, 12,8);
vector = bits(data,5,0);
generateIpi(type,cpu_id, vector);
return;
}
panic("Write to unknown IOB offset 0x%x\n", accessAddr);
}
void
Iob::writeJBus(PacketPtr pkt)
{
Addr accessAddr = pkt->getAddr() - iobJBusAddr;
int cpuid = pkt->req->getCpuNum();
int index;
uint64_t data;
if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
index = (accessAddr - JIntBusyAddr) >> 3;
data = pkt->get<uint64_t>();
jIntBusy[index].busy = bits(data,5,5);
return;
}
if (accessAddr == JIntABusyAddr) {
data = pkt->get<uint64_t>();
jIntBusy[cpuid].busy = bits(data,5,5);
return;
};
panic("Write to unknown JBus offset 0x%x\n", accessAddr);
}
void
Iob::receiveDeviceInterrupt(DeviceId devid)
{
assert(devid < NumDeviceIds);
if (intCtl[devid].mask)
return;
intCtl[devid].mask = true;
intCtl[devid].pend = true;
ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector);
}
void
Iob::generateIpi(Type type, int cpu_id, int vector)
{
// Only handle interrupts for the moment... Cpu Idle/reset/resume will be
// later
if (type != 0) {
warn("Ignoring IntVecDis write\n");
return;
}
assert(type == 0);
ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
}
bool
Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
{
// If we are already dealing with an interrupt for that cpu we can't deal
// with another one right now... come back later
if (jIntBusy[cpu_id].busy)
return false;
jIntBusy[cpu_id].busy = true;
jIntBusy[cpu_id].source = source;
jBusData0[cpu_id] = d0;
jBusData1[cpu_id] = d1;
ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec);
return true;
}
void
Iob::addressRanges(AddrRangeList &range_list)
{
range_list.clear();
range_list.push_back(RangeSize(iobManAddr, iobManSize));
range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize));
}
void
Iob::serialize(std::ostream &os)
{
SERIALIZE_SCALAR(jIntVec);
SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
for (int x = 0; x < NumDeviceIds; x++) {
nameOut(os, csprintf("%s.Int%d", name(), x));
paramOut(os, "cpu", intMan[x].cpu);
paramOut(os, "vector", intMan[x].vector);
paramOut(os, "mask", intCtl[x].mask);
paramOut(os, "pend", intCtl[x].pend);
};
for (int x = 0; x < MaxNiagaraProcs; x++) {
nameOut(os, csprintf("%s.jIntBusy%d", name(), x));
paramOut(os, "busy", jIntBusy[x].busy);
paramOut(os, "source", jIntBusy[x].source);
};
}
void
Iob::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(jIntVec);
UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
for (int x = 0; x < NumDeviceIds; x++) {
paramIn(cp, csprintf("%s.Int%d", name(), x), "cpu", intMan[x].cpu);
paramIn(cp, csprintf("%s.Int%d", name(), x), "vector", intMan[x].vector);
paramIn(cp, csprintf("%s.Int%d", name(), x), "mask", intCtl[x].mask);
paramIn(cp, csprintf("%s.Int%d", name(), x), "pend", intCtl[x].pend);
};
for (int x = 0; x < MaxNiagaraProcs; x++) {
paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "busy", jIntBusy[x].busy);
paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "source", jIntBusy[x].source);
};
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Iob)
Param<Tick> pio_latency;
SimObjectParam<Platform *> platform;
SimObjectParam<System *> system;
END_DECLARE_SIM_OBJECT_PARAMS(Iob)
BEGIN_INIT_SIM_OBJECT_PARAMS(Iob)
INIT_PARAM(pio_latency, "Programmed IO latency"),
INIT_PARAM(platform, "platform"),
INIT_PARAM(system, "system object")
END_INIT_SIM_OBJECT_PARAMS(Iob)
CREATE_SIM_OBJECT(Iob)
{
Iob::Params *p = new Iob::Params;
p->name = getInstanceName();
p->pio_delay = pio_latency;
p->platform = platform;
p->system = system;
return new Iob(p);
}
REGISTER_SIM_OBJECT("Iob", Iob)

153
src/dev/sparc/iob.hh Normal file
View file

@ -0,0 +1,153 @@
/*
* Copyright (c) 2006 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.
*
* Authors: Ali Saidi
*/
/** @file
* This device implements the niagara I/O Bridge chip. The device manages
* internal (ipi) and external (serial, pci via jbus).
*/
#ifndef __DEV_SPARC_IOB_HH__
#define __DEV_SPARC_IOB_HH__
#include "base/range.hh"
#include "dev/io_device.hh"
#include "dev/disk_image.hh"
class IntrControl;
const int MaxNiagaraProcs = 32;
// IOB Managment Addresses
const Addr IntManAddr = 0x0000;
const Addr IntManSize = 0x0020;
const Addr IntCtlAddr = 0x0400;
const Addr IntCtlSize = 0x0020;
const Addr JIntVecAddr = 0x0A00;
const Addr IntVecDisAddr = 0x0800;
const Addr IntVecDisSize = 0x0100;
// IOB Control Addresses
const Addr JIntData0Addr = 0x0400;
const Addr JIntData1Addr = 0x0500;
const Addr JIntDataA0Addr = 0x0600;
const Addr JIntDataA1Addr = 0x0700;
const Addr JIntBusyAddr = 0x0900;
const Addr JIntBusySize = 0x0100;
const Addr JIntABusyAddr = 0x0B00;
// IOB Masks
const uint64_t IntManMask = 0x01F3F;
const uint64_t IntCtlMask = 0x00006;
const uint64_t JIntVecMask = 0x0003F;
const uint64_t IntVecDis = 0x31F3F;
const uint64_t JIntBusyMask = 0x0003F;
class Iob : public PioDevice
{
private:
IntrControl *ic;
Addr iobManAddr;
Addr iobManSize;
Addr iobJBusAddr;
Addr iobJBusSize;
Tick pioDelay;
enum DeviceId {
Interal = 0,
Error = 1,
SSI = 2,
Reserved = 3,
NumDeviceIds
};
struct IntMan {
int cpu;
int vector;
};
struct IntCtl {
bool mask;
bool pend;
};
struct IntBusy {
bool busy;
int source;
};
enum Type {
Interrupt,
Reset,
Idle,
Resume
};
IntMan intMan[NumDeviceIds];
IntCtl intCtl[NumDeviceIds];
uint64_t jIntVec;
uint64_t jBusData0[MaxNiagaraProcs];
uint64_t jBusData1[MaxNiagaraProcs];
IntBusy jIntBusy[MaxNiagaraProcs];
void writeIob(PacketPtr pkt);
void writeJBus(PacketPtr pkt);
void readIob(PacketPtr pkt);
void readJBus(PacketPtr pkt);
public:
struct Params : public PioDevice::Params
{
Tick pio_delay;
};
protected:
const Params *params() const { return (const Params*)_params; }
public:
Iob(Params *p);
virtual Tick read(PacketPtr pkt);
virtual Tick write(PacketPtr pkt);
void generateIpi(Type type, int cpu_id, int vector);
void receiveDeviceInterrupt(DeviceId devid);
bool receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1);
void addressRanges(AddrRangeList &range_list);
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
#endif //__DEV_SPARC_IOB_HH__

View file

@ -1,6 +1,6 @@
from m5.params import *
from m5.proxy import *
from Device import BasicPioDevice, IsaFake, BadAddr
from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr
from Uart import Uart8250
from Platform import Platform
from SimConsole import SimConsole
@ -16,6 +16,10 @@ class DumbTOD(BasicPioDevice):
time = Param.Time('01/01/2009', "System time to use ('Now' for real time)")
pio_addr = 0xfff0c1fff8
class Iob(PioDevice):
type = 'Iob'
pio_latency = Param.Latency('1ns', "Programed IO latency in simticks")
class T1000(Platform):
type = 'T1000'
@ -28,9 +32,6 @@ class T1000(Platform):
ret_data64=0x0000000000000000, update_data=False)
#warn_access="Accessing Memory Banks -- Unimplemented!")
fake_iob = IsaFake(pio_addr=0x9800000000, pio_size=0x100000000)
#warn_access="Accessing IOB -- Unimplemented!")
fake_jbi = IsaFake(pio_addr=0x8000000000, pio_size=0x100000000)
#warn_access="Accessing JBI -- Unimplemented!")
@ -76,6 +77,13 @@ class T1000(Platform):
pconsole = SimConsole()
puart0 = Uart8250(pio_addr=0x1f10000000)
iob = Iob()
# Attach I/O devices that are on chip
def attachOnChipIO(self, bus):
self.iob.pio = bus.port
self.htod.pio = bus.port
# Attach I/O devices to specified bus object. Can't do this
# earlier, since the bus object itself is typically defined at the
# System level.
@ -84,8 +92,6 @@ class T1000(Platform):
self.puart0.sim_console = self.pconsole
self.fake_clk.pio = bus.port
self.fake_membnks.pio = bus.port
self.fake_iob.pio = bus.port
self.fake_jbi.pio = bus.port
self.fake_l2_1.pio = bus.port
self.fake_l2_2.pio = bus.port
self.fake_l2_3.pio = bus.port
@ -95,6 +101,6 @@ class T1000(Platform):
self.fake_l2esr_3.pio = bus.port
self.fake_l2esr_4.pio = bus.port
self.fake_ssi.pio = bus.port
self.fake_jbi.pio = bus.port
self.puart0.pio = bus.port
self.hvuart.pio = bus.port
self.htod.pio = bus.port