Adding gem5 source to svn.
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1819 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
34
simulators/gem5/src/dev/BadDevice.py
Normal file
34
simulators/gem5/src/dev/BadDevice.py
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.params import *
|
||||
from Device import BasicPioDevice
|
||||
|
||||
class BadDevice(BasicPioDevice):
|
||||
type = 'BadDevice'
|
||||
devicename = Param.String("Name of device to error on")
|
||||
60
simulators/gem5/src/dev/CopyEngine.py
Normal file
60
simulators/gem5/src/dev/CopyEngine.py
Normal file
@ -0,0 +1,60 @@
|
||||
# Copyright (c) 2008 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
|
||||
|
||||
from m5.SimObject import SimObject
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from Pci import PciDevice
|
||||
|
||||
class CopyEngine(PciDevice):
|
||||
type = 'CopyEngine'
|
||||
dma = VectorMasterPort("Copy engine DMA port")
|
||||
VendorID = 0x8086
|
||||
DeviceID = 0x1a38
|
||||
Revision = 0xA2 # CM2 stepping (newest listed)
|
||||
SubsystemID = 0
|
||||
SubsystemVendorID = 0
|
||||
Status = 0x0000
|
||||
SubClassCode = 0x08
|
||||
ClassCode = 0x80
|
||||
ProgIF = 0x00
|
||||
MaximumLatency = 0x00
|
||||
MinimumGrant = 0xff
|
||||
InterruptLine = 0x20
|
||||
InterruptPin = 0x01
|
||||
BAR0Size = '1kB'
|
||||
|
||||
ChanCnt = Param.UInt8(4, "Number of DMA channels that exist on device")
|
||||
XferCap = Param.MemorySize('4kB', "Number of bits of transfer size that are supported")
|
||||
|
||||
|
||||
clock = Param.Clock('500MHz', "Clock speed of the device")
|
||||
latBeforeBegin = Param.Latency('20ns', "Latency after a DMA command is seen before it's proccessed")
|
||||
latAfterCompletion = Param.Latency('20ns', "Latency after a DMA command is complete before it's reported as such")
|
||||
|
||||
|
||||
73
simulators/gem5/src/dev/Device.py
Normal file
73
simulators/gem5/src/dev/Device.py
Normal file
@ -0,0 +1,73 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from MemObject import MemObject
|
||||
|
||||
class PioDevice(MemObject):
|
||||
type = 'PioDevice'
|
||||
abstract = True
|
||||
pio = SlavePort("Programmed I/O port")
|
||||
system = Param.System(Parent.any, "System this device is part of")
|
||||
|
||||
class BasicPioDevice(PioDevice):
|
||||
type = 'BasicPioDevice'
|
||||
abstract = True
|
||||
pio_addr = Param.Addr("Device Address")
|
||||
pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
|
||||
|
||||
class DmaDevice(PioDevice):
|
||||
type = 'DmaDevice'
|
||||
abstract = True
|
||||
dma = MasterPort("DMA port")
|
||||
min_backoff_delay = Param.Latency('4ns',
|
||||
"min time between a nack packet being received and the next request made by the device")
|
||||
max_backoff_delay = Param.Latency('10us',
|
||||
"max time between a nack packet being received and the next request made by the device")
|
||||
|
||||
|
||||
|
||||
class IsaFake(BasicPioDevice):
|
||||
type = 'IsaFake'
|
||||
pio_size = Param.Addr(0x8, "Size of address range")
|
||||
ret_data8 = Param.UInt8(0xFF, "Default data to return")
|
||||
ret_data16 = Param.UInt16(0xFFFF, "Default data to return")
|
||||
ret_data32 = Param.UInt32(0xFFFFFFFF, "Default data to return")
|
||||
ret_data64 = Param.UInt64(0xFFFFFFFFFFFFFFFF, "Default data to return")
|
||||
ret_bad_addr = Param.Bool(False, "Return pkt status bad address on access")
|
||||
update_data = Param.Bool(False, "Update the data that is returned on writes")
|
||||
warn_access = Param.String("", "String to print when device is accessed")
|
||||
fake_mem = Param.Bool(False,
|
||||
"Is this device acting like a memory and thus may get a cache line sized req")
|
||||
|
||||
class BadAddr(IsaFake):
|
||||
pio_addr = 0
|
||||
ret_bad_addr = Param.Bool(True, "Return pkt status bad address on access")
|
||||
|
||||
|
||||
45
simulators/gem5/src/dev/DiskImage.py
Normal file
45
simulators/gem5/src/dev/DiskImage.py
Normal file
@ -0,0 +1,45 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.SimObject import SimObject
|
||||
from m5.params import *
|
||||
class DiskImage(SimObject):
|
||||
type = 'DiskImage'
|
||||
abstract = True
|
||||
image_file = Param.String("disk image file")
|
||||
read_only = Param.Bool(False, "read only image")
|
||||
|
||||
class RawDiskImage(DiskImage):
|
||||
type = 'RawDiskImage'
|
||||
|
||||
class CowDiskImage(DiskImage):
|
||||
type = 'CowDiskImage'
|
||||
child = Param.DiskImage(RawDiskImage(read_only=True),
|
||||
"child image")
|
||||
table_size = Param.Int(65536, "initial table size")
|
||||
image_file = ""
|
||||
213
simulators/gem5/src/dev/Ethernet.py
Normal file
213
simulators/gem5/src/dev/Ethernet.py
Normal file
@ -0,0 +1,213 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.SimObject import SimObject
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from Pci import PciDevice
|
||||
|
||||
class EtherObject(SimObject):
|
||||
type = 'EtherObject'
|
||||
abstract = True
|
||||
|
||||
class EtherLink(EtherObject):
|
||||
type = 'EtherLink'
|
||||
int0 = SlavePort("interface 0")
|
||||
int1 = SlavePort("interface 1")
|
||||
delay = Param.Latency('0us', "packet transmit delay")
|
||||
delay_var = Param.Latency('0ns', "packet transmit delay variability")
|
||||
speed = Param.NetworkBandwidth('1Gbps', "link speed")
|
||||
dump = Param.EtherDump(NULL, "dump object")
|
||||
|
||||
class EtherBus(EtherObject):
|
||||
type = 'EtherBus'
|
||||
loopback = Param.Bool(True, "send packet back to the sending interface")
|
||||
dump = Param.EtherDump(NULL, "dump object")
|
||||
speed = Param.NetworkBandwidth('100Mbps', "bus speed in bits per second")
|
||||
|
||||
class EtherTap(EtherObject):
|
||||
type = 'EtherTap'
|
||||
bufsz = Param.Int(10000, "tap buffer size")
|
||||
dump = Param.EtherDump(NULL, "dump object")
|
||||
port = Param.UInt16(3500, "tap port")
|
||||
|
||||
class EtherDump(SimObject):
|
||||
type = 'EtherDump'
|
||||
file = Param.String("dump file")
|
||||
maxlen = Param.Int(96, "max portion of packet data to dump")
|
||||
|
||||
class EtherDevice(PciDevice):
|
||||
type = 'EtherDevice'
|
||||
abstract = True
|
||||
interface = MasterPort("Ethernet Interface")
|
||||
|
||||
class IGbE(EtherDevice):
|
||||
# Base class for two IGbE adapters listed above
|
||||
type = 'IGbE'
|
||||
hardware_address = Param.EthernetAddr(NextEthernetAddr,
|
||||
"Ethernet Hardware Address")
|
||||
use_flow_control = Param.Bool(False,
|
||||
"Should we use xon/xoff flow contorl (UNIMPLEMENTD)")
|
||||
rx_fifo_size = Param.MemorySize('384kB', "Size of the rx FIFO")
|
||||
tx_fifo_size = Param.MemorySize('384kB', "Size of the tx FIFO")
|
||||
rx_desc_cache_size = Param.Int(64,
|
||||
"Number of enteries in the rx descriptor cache")
|
||||
tx_desc_cache_size = Param.Int(64,
|
||||
"Number of enteries in the rx descriptor cache")
|
||||
clock = Param.Clock('500MHz', "Clock speed of the device")
|
||||
VendorID = 0x8086
|
||||
SubsystemID = 0x1008
|
||||
SubsystemVendorID = 0x8086
|
||||
Status = 0x0000
|
||||
SubClassCode = 0x00
|
||||
ClassCode = 0x02
|
||||
ProgIF = 0x00
|
||||
BAR0 = 0x00000000
|
||||
BAR1 = 0x00000000
|
||||
BAR2 = 0x00000000
|
||||
BAR3 = 0x00000000
|
||||
BAR4 = 0x00000000
|
||||
BAR5 = 0x00000000
|
||||
MaximumLatency = 0x00
|
||||
MinimumGrant = 0xff
|
||||
InterruptLine = 0x1e
|
||||
InterruptPin = 0x01
|
||||
BAR0Size = '128kB'
|
||||
wb_delay = Param.Latency('10ns', "delay before desc writeback occurs")
|
||||
fetch_delay = Param.Latency('10ns', "delay before desc fetch occurs")
|
||||
fetch_comp_delay = Param.Latency('10ns', "delay after desc fetch occurs")
|
||||
wb_comp_delay = Param.Latency('10ns', "delay after desc wb occurs")
|
||||
tx_read_delay = Param.Latency('0ns', "delay after tx dma read")
|
||||
rx_write_delay = Param.Latency('0ns', "delay after rx dma read")
|
||||
phy_pid = Param.UInt16("Phy PID that corresponds to device ID")
|
||||
phy_epid = Param.UInt16("Phy EPID that corresponds to device ID")
|
||||
|
||||
class IGbE_e1000(IGbE):
|
||||
# Older Intel 8254x based gigabit ethernet adapter
|
||||
# Uses Intel e1000 driver
|
||||
DeviceID = 0x1075
|
||||
phy_pid = 0x02A8
|
||||
phy_epid = 0x0380
|
||||
|
||||
class IGbE_igb(IGbE):
|
||||
# Newer Intel 8257x based gigabit ethernet adapter
|
||||
# Uses Intel igb driver and in theory supports packet splitting and LRO
|
||||
DeviceID = 0x10C9
|
||||
phy_pid = 0x0141
|
||||
phy_epid = 0x0CC0
|
||||
|
||||
class EtherDevBase(EtherDevice):
|
||||
type = 'EtherDevBase'
|
||||
abstract = True
|
||||
hardware_address = Param.EthernetAddr(NextEthernetAddr,
|
||||
"Ethernet Hardware Address")
|
||||
|
||||
clock = Param.Clock('0ns', "State machine processor frequency")
|
||||
|
||||
dma_read_delay = Param.Latency('0us', "fixed delay for dma reads")
|
||||
dma_read_factor = Param.Latency('0us', "multiplier for dma reads")
|
||||
dma_write_delay = Param.Latency('0us', "fixed delay for dma writes")
|
||||
dma_write_factor = Param.Latency('0us', "multiplier for dma writes")
|
||||
|
||||
rx_delay = Param.Latency('1us', "Receive Delay")
|
||||
tx_delay = Param.Latency('1us', "Transmit Delay")
|
||||
rx_fifo_size = Param.MemorySize('512kB', "max size of rx fifo")
|
||||
tx_fifo_size = Param.MemorySize('512kB', "max size of tx fifo")
|
||||
|
||||
rx_filter = Param.Bool(True, "Enable Receive Filter")
|
||||
intr_delay = Param.Latency('10us', "Interrupt propagation delay")
|
||||
rx_thread = Param.Bool(False, "dedicated kernel thread for transmit")
|
||||
tx_thread = Param.Bool(False, "dedicated kernel threads for receive")
|
||||
rss = Param.Bool(False, "Receive Side Scaling")
|
||||
|
||||
class NSGigE(EtherDevBase):
|
||||
type = 'NSGigE'
|
||||
|
||||
dma_data_free = Param.Bool(False, "DMA of Data is free")
|
||||
dma_desc_free = Param.Bool(False, "DMA of Descriptors is free")
|
||||
dma_no_allocate = Param.Bool(True, "Should we allocate cache on read")
|
||||
|
||||
VendorID = 0x100B
|
||||
DeviceID = 0x0022
|
||||
Status = 0x0290
|
||||
SubClassCode = 0x00
|
||||
ClassCode = 0x02
|
||||
ProgIF = 0x00
|
||||
BAR0 = 0x00000001
|
||||
BAR1 = 0x00000000
|
||||
BAR2 = 0x00000000
|
||||
BAR3 = 0x00000000
|
||||
BAR4 = 0x00000000
|
||||
BAR5 = 0x00000000
|
||||
MaximumLatency = 0x34
|
||||
MinimumGrant = 0xb0
|
||||
InterruptLine = 0x1e
|
||||
InterruptPin = 0x01
|
||||
BAR0Size = '256B'
|
||||
BAR1Size = '4kB'
|
||||
|
||||
|
||||
|
||||
class Sinic(EtherDevBase):
|
||||
type = 'Sinic'
|
||||
cxx_class = 'Sinic::Device'
|
||||
|
||||
rx_max_copy = Param.MemorySize('1514B', "rx max copy")
|
||||
tx_max_copy = Param.MemorySize('16kB', "tx max copy")
|
||||
rx_max_intr = Param.UInt32(10, "max rx packets per interrupt")
|
||||
rx_fifo_threshold = Param.MemorySize('384kB', "rx fifo high threshold")
|
||||
rx_fifo_low_mark = Param.MemorySize('128kB', "rx fifo low threshold")
|
||||
tx_fifo_high_mark = Param.MemorySize('384kB', "tx fifo high threshold")
|
||||
tx_fifo_threshold = Param.MemorySize('128kB', "tx fifo low threshold")
|
||||
virtual_count = Param.UInt32(1, "Virtualized SINIC")
|
||||
zero_copy_size = Param.UInt32(64, "Bytes to copy if below threshold")
|
||||
zero_copy_threshold = Param.UInt32(256,
|
||||
"Only zero copy above this threshold")
|
||||
zero_copy = Param.Bool(False, "Zero copy receive")
|
||||
delay_copy = Param.Bool(False, "Delayed copy transmit")
|
||||
virtual_addr = Param.Bool(False, "Virtual addressing")
|
||||
|
||||
VendorID = 0x1291
|
||||
DeviceID = 0x1293
|
||||
Status = 0x0290
|
||||
SubClassCode = 0x00
|
||||
ClassCode = 0x02
|
||||
ProgIF = 0x00
|
||||
BAR0 = 0x00000000
|
||||
BAR1 = 0x00000000
|
||||
BAR2 = 0x00000000
|
||||
BAR3 = 0x00000000
|
||||
BAR4 = 0x00000000
|
||||
BAR5 = 0x00000000
|
||||
MaximumLatency = 0x34
|
||||
MinimumGrant = 0xb0
|
||||
InterruptLine = 0x1e
|
||||
InterruptPin = 0x01
|
||||
BAR0Size = '64kB'
|
||||
|
||||
|
||||
68
simulators/gem5/src/dev/Ide.py
Normal file
68
simulators/gem5/src/dev/Ide.py
Normal file
@ -0,0 +1,68 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.SimObject import SimObject
|
||||
from m5.params import *
|
||||
from Pci import PciDevice
|
||||
|
||||
class IdeID(Enum): vals = ['master', 'slave']
|
||||
|
||||
class IdeDisk(SimObject):
|
||||
type = 'IdeDisk'
|
||||
delay = Param.Latency('1us', "Fixed disk delay in microseconds")
|
||||
driveID = Param.IdeID('master', "Drive ID")
|
||||
image = Param.DiskImage("Disk image")
|
||||
|
||||
class IdeController(PciDevice):
|
||||
type = 'IdeController'
|
||||
disks = VectorParam.IdeDisk("IDE disks attached to this controller")
|
||||
|
||||
VendorID = 0x8086
|
||||
DeviceID = 0x7111
|
||||
Command = 0x0
|
||||
Status = 0x280
|
||||
Revision = 0x0
|
||||
ClassCode = 0x01
|
||||
SubClassCode = 0x01
|
||||
ProgIF = 0x85
|
||||
BAR0 = 0x00000001
|
||||
BAR1 = 0x00000001
|
||||
BAR2 = 0x00000001
|
||||
BAR3 = 0x00000001
|
||||
BAR4 = 0x00000001
|
||||
BAR5 = 0x00000001
|
||||
InterruptLine = 0x1f
|
||||
InterruptPin = 0x01
|
||||
BAR0Size = '8B'
|
||||
BAR1Size = '4B'
|
||||
BAR2Size = '8B'
|
||||
BAR3Size = '4B'
|
||||
BAR4Size = '16B'
|
||||
|
||||
io_shift = Param.UInt32(0x0, "IO port shift");
|
||||
ctrl_offset = Param.UInt32(0x0, "IDE disk control offset")
|
||||
94
simulators/gem5/src/dev/Pci.py
Normal file
94
simulators/gem5/src/dev/Pci.py
Normal file
@ -0,0 +1,94 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.SimObject import SimObject
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from Device import BasicPioDevice, DmaDevice, PioDevice
|
||||
|
||||
class PciConfigAll(PioDevice):
|
||||
type = 'PciConfigAll'
|
||||
platform = Param.Platform(Parent.any, "Platform this device is part of.")
|
||||
pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
|
||||
bus = Param.UInt8(0x00, "PCI bus to act as config space for")
|
||||
size = Param.MemorySize32('16MB', "Size of config space")
|
||||
|
||||
|
||||
class PciDevice(DmaDevice):
|
||||
type = 'PciDevice'
|
||||
abstract = True
|
||||
platform = Param.Platform(Parent.any, "Platform this device is part of.")
|
||||
config = SlavePort("PCI configuration space port")
|
||||
pci_bus = Param.Int("PCI bus")
|
||||
pci_dev = Param.Int("PCI device number")
|
||||
pci_func = Param.Int("PCI function code")
|
||||
pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
|
||||
config_latency = Param.Latency('20ns', "Config read or write latency")
|
||||
|
||||
VendorID = Param.UInt16("Vendor ID")
|
||||
DeviceID = Param.UInt16("Device ID")
|
||||
Command = Param.UInt16(0, "Command")
|
||||
Status = Param.UInt16(0, "Status")
|
||||
Revision = Param.UInt8(0, "Device")
|
||||
ProgIF = Param.UInt8(0, "Programming Interface")
|
||||
SubClassCode = Param.UInt8(0, "Sub-Class Code")
|
||||
ClassCode = Param.UInt8(0, "Class Code")
|
||||
CacheLineSize = Param.UInt8(0, "System Cacheline Size")
|
||||
LatencyTimer = Param.UInt8(0, "PCI Latency Timer")
|
||||
HeaderType = Param.UInt8(0, "PCI Header Type")
|
||||
BIST = Param.UInt8(0, "Built In Self Test")
|
||||
|
||||
BAR0 = Param.UInt32(0x00, "Base Address Register 0")
|
||||
BAR1 = Param.UInt32(0x00, "Base Address Register 1")
|
||||
BAR2 = Param.UInt32(0x00, "Base Address Register 2")
|
||||
BAR3 = Param.UInt32(0x00, "Base Address Register 3")
|
||||
BAR4 = Param.UInt32(0x00, "Base Address Register 4")
|
||||
BAR5 = Param.UInt32(0x00, "Base Address Register 5")
|
||||
BAR0Size = Param.MemorySize32('0B', "Base Address Register 0 Size")
|
||||
BAR1Size = Param.MemorySize32('0B', "Base Address Register 1 Size")
|
||||
BAR2Size = Param.MemorySize32('0B', "Base Address Register 2 Size")
|
||||
BAR3Size = Param.MemorySize32('0B', "Base Address Register 3 Size")
|
||||
BAR4Size = Param.MemorySize32('0B', "Base Address Register 4 Size")
|
||||
BAR5Size = Param.MemorySize32('0B', "Base Address Register 5 Size")
|
||||
BAR0LegacyIO = Param.Bool(False, "Whether BAR0 is hardwired legacy IO")
|
||||
BAR1LegacyIO = Param.Bool(False, "Whether BAR1 is hardwired legacy IO")
|
||||
BAR2LegacyIO = Param.Bool(False, "Whether BAR2 is hardwired legacy IO")
|
||||
BAR3LegacyIO = Param.Bool(False, "Whether BAR3 is hardwired legacy IO")
|
||||
BAR4LegacyIO = Param.Bool(False, "Whether BAR4 is hardwired legacy IO")
|
||||
BAR5LegacyIO = Param.Bool(False, "Whether BAR5 is hardwired legacy IO")
|
||||
|
||||
CardbusCIS = Param.UInt32(0x00, "Cardbus Card Information Structure")
|
||||
SubsystemID = Param.UInt16(0x00, "Subsystem ID")
|
||||
SubsystemVendorID = Param.UInt16(0x00, "Subsystem Vendor ID")
|
||||
ExpansionROM = Param.UInt32(0x00, "Expansion ROM Base Address")
|
||||
InterruptLine = Param.UInt8(0x00, "Interrupt Line")
|
||||
InterruptPin = Param.UInt8(0x00, "Interrupt Pin")
|
||||
MaximumLatency = Param.UInt8(0x00, "Maximum Latency")
|
||||
MinimumGrant = Param.UInt8(0x00, "Minimum Grant")
|
||||
|
||||
|
||||
35
simulators/gem5/src/dev/Platform.py
Normal file
35
simulators/gem5/src/dev/Platform.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.SimObject import SimObject
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
class Platform(SimObject):
|
||||
type = 'Platform'
|
||||
abstract = True
|
||||
intrctrl = Param.IntrControl(Parent.any, "interrupt controller")
|
||||
111
simulators/gem5/src/dev/SConscript
Normal file
111
simulators/gem5/src/dev/SConscript
Normal file
@ -0,0 +1,111 @@
|
||||
# -*- mode:python -*-
|
||||
|
||||
# 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: Steve Reinhardt
|
||||
# Gabe Black
|
||||
|
||||
Import('*')
|
||||
|
||||
if env['TARGET_ISA'] == 'no':
|
||||
Return()
|
||||
|
||||
SimObject('BadDevice.py')
|
||||
SimObject('CopyEngine.py')
|
||||
SimObject('Device.py')
|
||||
SimObject('DiskImage.py')
|
||||
SimObject('Ethernet.py')
|
||||
SimObject('Ide.py')
|
||||
SimObject('Pci.py')
|
||||
SimObject('Platform.py')
|
||||
SimObject('SimpleDisk.py')
|
||||
SimObject('Terminal.py')
|
||||
SimObject('Uart.py')
|
||||
|
||||
Source('baddev.cc')
|
||||
Source('copy_engine.cc')
|
||||
Source('disk_image.cc')
|
||||
Source('dma_device.cc')
|
||||
Source('etherbus.cc')
|
||||
Source('etherdevice.cc')
|
||||
Source('etherdump.cc')
|
||||
Source('etherint.cc')
|
||||
Source('etherlink.cc')
|
||||
Source('etherpkt.cc')
|
||||
Source('ethertap.cc')
|
||||
Source('i8254xGBe.cc')
|
||||
Source('ide_ctrl.cc')
|
||||
Source('ide_disk.cc')
|
||||
Source('intel_8254_timer.cc')
|
||||
Source('io_device.cc')
|
||||
Source('isa_fake.cc')
|
||||
Source('mc146818.cc')
|
||||
Source('ns_gige.cc')
|
||||
Source('pciconfigall.cc')
|
||||
Source('pcidev.cc')
|
||||
Source('pktfifo.cc')
|
||||
Source('platform.cc')
|
||||
Source('ps2.cc')
|
||||
Source('simple_disk.cc')
|
||||
Source('sinic.cc')
|
||||
Source('terminal.cc')
|
||||
Source('uart.cc')
|
||||
Source('uart8250.cc')
|
||||
|
||||
DebugFlag('DiskImageRead')
|
||||
DebugFlag('DiskImageWrite')
|
||||
DebugFlag('DMA')
|
||||
DebugFlag('DMACopyEngine')
|
||||
DebugFlag('Ethernet')
|
||||
DebugFlag('EthernetCksum')
|
||||
DebugFlag('EthernetDMA')
|
||||
DebugFlag('EthernetData')
|
||||
DebugFlag('EthernetDesc')
|
||||
DebugFlag('EthernetEEPROM')
|
||||
DebugFlag('EthernetIntr')
|
||||
DebugFlag('EthernetPIO')
|
||||
DebugFlag('EthernetSM')
|
||||
DebugFlag('IdeCtrl')
|
||||
DebugFlag('IdeDisk')
|
||||
DebugFlag('Intel8254Timer')
|
||||
DebugFlag('IsaFake')
|
||||
DebugFlag('MC146818')
|
||||
DebugFlag('PCIDEV')
|
||||
DebugFlag('PciConfigAll')
|
||||
DebugFlag('SimpleDisk')
|
||||
DebugFlag('SimpleDiskData')
|
||||
DebugFlag('Terminal')
|
||||
DebugFlag('TerminalVerbose')
|
||||
DebugFlag('Uart')
|
||||
|
||||
CompoundFlag('DiskImageAll', [ 'DiskImageRead', 'DiskImageWrite' ])
|
||||
CompoundFlag('EthernetAll', [ 'Ethernet', 'EthernetPIO', 'EthernetDMA',
|
||||
'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM',
|
||||
'EthernetCksum', 'EthernetEEPROM' ])
|
||||
CompoundFlag('EthernetNoData', [ 'Ethernet', 'EthernetPIO', 'EthernetDesc',
|
||||
'EthernetIntr', 'EthernetSM', 'EthernetCksum' ])
|
||||
CompoundFlag('IdeAll', [ 'IdeCtrl', 'IdeDisk' ])
|
||||
35
simulators/gem5/src/dev/SimpleDisk.py
Normal file
35
simulators/gem5/src/dev/SimpleDisk.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.SimObject import SimObject
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
class SimpleDisk(SimObject):
|
||||
type = 'SimpleDisk'
|
||||
disk = Param.DiskImage("Disk Image")
|
||||
system = Param.System(Parent.any, "System Pointer")
|
||||
38
simulators/gem5/src/dev/Terminal.py
Normal file
38
simulators/gem5/src/dev/Terminal.py
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.SimObject import SimObject
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
|
||||
class Terminal(SimObject):
|
||||
type = 'Terminal'
|
||||
intr_control = Param.IntrControl(Parent.any, "interrupt controller")
|
||||
port = Param.TcpPort(3456, "listen port")
|
||||
number = Param.Int(0, "terminal number")
|
||||
output = Param.Bool(True, "Enable output dump to file")
|
||||
40
simulators/gem5/src/dev/Uart.py
Normal file
40
simulators/gem5/src/dev/Uart.py
Normal file
@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from Device import BasicPioDevice
|
||||
|
||||
class Uart(BasicPioDevice):
|
||||
type = 'Uart'
|
||||
abstract = True
|
||||
platform = Param.Platform(Parent.any, "Platform this device is part of.")
|
||||
terminal = Param.Terminal(Parent.any, "The terminal")
|
||||
|
||||
class Uart8250(Uart):
|
||||
type = 'Uart8250'
|
||||
40
simulators/gem5/src/dev/alpha/AlphaBackdoor.py
Normal file
40
simulators/gem5/src/dev/alpha/AlphaBackdoor.py
Normal file
@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.defines import buildEnv
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from Device import BasicPioDevice
|
||||
|
||||
class AlphaBackdoor(BasicPioDevice):
|
||||
type = 'AlphaBackdoor'
|
||||
cpu = Param.BaseCPU(Parent.cpu[0], "Processor")
|
||||
disk = Param.SimpleDisk("Simple Disk")
|
||||
terminal = Param.Terminal(Parent.any, "The console terminal")
|
||||
platform = Param.Platform(Parent.any, "Platform this device is part of.")
|
||||
system = Param.AlphaSystem(Parent.any, "system object")
|
||||
45
simulators/gem5/src/dev/alpha/SConscript
Normal file
45
simulators/gem5/src/dev/alpha/SConscript
Normal file
@ -0,0 +1,45 @@
|
||||
# -*- mode:python -*-
|
||||
|
||||
# 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: Steve Reinhardt
|
||||
# Gabe Black
|
||||
|
||||
Import('*')
|
||||
|
||||
if env['TARGET_ISA'] == 'alpha':
|
||||
SimObject('AlphaBackdoor.py')
|
||||
SimObject('Tsunami.py')
|
||||
|
||||
Source('backdoor.cc')
|
||||
Source('tsunami.cc')
|
||||
Source('tsunami_cchip.cc')
|
||||
Source('tsunami_io.cc')
|
||||
Source('tsunami_pchip.cc')
|
||||
|
||||
DebugFlag('AlphaBackdoor')
|
||||
DebugFlag('Tsunami')
|
||||
122
simulators/gem5/src/dev/alpha/Tsunami.py
Normal file
122
simulators/gem5/src/dev/alpha/Tsunami.py
Normal file
@ -0,0 +1,122 @@
|
||||
# Copyright (c) 2005-2007 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: Nathan Binkert
|
||||
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from BadDevice import BadDevice
|
||||
from AlphaBackdoor import AlphaBackdoor
|
||||
from Device import BasicPioDevice, IsaFake, BadAddr
|
||||
from Pci import PciConfigAll
|
||||
from Platform import Platform
|
||||
from Uart import Uart8250
|
||||
|
||||
class TsunamiCChip(BasicPioDevice):
|
||||
type = 'TsunamiCChip'
|
||||
tsunami = Param.Tsunami(Parent.any, "Tsunami")
|
||||
|
||||
class TsunamiIO(BasicPioDevice):
|
||||
type = 'TsunamiIO'
|
||||
time = Param.Time('01/01/2009',
|
||||
"System time to use ('Now' for actual time)")
|
||||
year_is_bcd = Param.Bool(False,
|
||||
"The RTC should interpret the year as a BCD value")
|
||||
tsunami = Param.Tsunami(Parent.any, "Tsunami")
|
||||
frequency = Param.Frequency('1024Hz', "frequency of interrupts")
|
||||
|
||||
class TsunamiPChip(BasicPioDevice):
|
||||
type = 'TsunamiPChip'
|
||||
tsunami = Param.Tsunami(Parent.any, "Tsunami")
|
||||
|
||||
class Tsunami(Platform):
|
||||
type = 'Tsunami'
|
||||
system = Param.System(Parent.any, "system")
|
||||
|
||||
cchip = TsunamiCChip(pio_addr=0x801a0000000)
|
||||
pchip = TsunamiPChip(pio_addr=0x80180000000)
|
||||
pciconfig = PciConfigAll()
|
||||
fake_sm_chip = IsaFake(pio_addr=0x801fc000370)
|
||||
|
||||
fake_uart1 = IsaFake(pio_addr=0x801fc0002f8)
|
||||
fake_uart2 = IsaFake(pio_addr=0x801fc0003e8)
|
||||
fake_uart3 = IsaFake(pio_addr=0x801fc0002e8)
|
||||
fake_uart4 = IsaFake(pio_addr=0x801fc0003f0)
|
||||
|
||||
fake_ppc = IsaFake(pio_addr=0x801fc0003bb)
|
||||
|
||||
fake_OROM = IsaFake(pio_addr=0x800000a0000, pio_size=0x60000)
|
||||
|
||||
fake_pnp_addr = IsaFake(pio_addr=0x801fc000279)
|
||||
fake_pnp_write = IsaFake(pio_addr=0x801fc000a79)
|
||||
fake_pnp_read0 = IsaFake(pio_addr=0x801fc000203)
|
||||
fake_pnp_read1 = IsaFake(pio_addr=0x801fc000243)
|
||||
fake_pnp_read2 = IsaFake(pio_addr=0x801fc000283)
|
||||
fake_pnp_read3 = IsaFake(pio_addr=0x801fc0002c3)
|
||||
fake_pnp_read4 = IsaFake(pio_addr=0x801fc000303)
|
||||
fake_pnp_read5 = IsaFake(pio_addr=0x801fc000343)
|
||||
fake_pnp_read6 = IsaFake(pio_addr=0x801fc000383)
|
||||
fake_pnp_read7 = IsaFake(pio_addr=0x801fc0003c3)
|
||||
|
||||
fake_ata0 = IsaFake(pio_addr=0x801fc0001f0)
|
||||
fake_ata1 = IsaFake(pio_addr=0x801fc000170)
|
||||
|
||||
fb = BadDevice(pio_addr=0x801fc0003d0, devicename='FrameBuffer')
|
||||
io = TsunamiIO(pio_addr=0x801fc000000)
|
||||
uart = Uart8250(pio_addr=0x801fc0003f8)
|
||||
backdoor = AlphaBackdoor(pio_addr=0x80200000000, disk=Parent.simple_disk)
|
||||
|
||||
# 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.
|
||||
def attachIO(self, bus):
|
||||
self.cchip.pio = bus.master
|
||||
self.pchip.pio = bus.master
|
||||
self.pciconfig.pio = bus.default
|
||||
bus.use_default_range = True
|
||||
self.fake_sm_chip.pio = bus.master
|
||||
self.fake_uart1.pio = bus.master
|
||||
self.fake_uart2.pio = bus.master
|
||||
self.fake_uart3.pio = bus.master
|
||||
self.fake_uart4.pio = bus.master
|
||||
self.fake_ppc.pio = bus.master
|
||||
self.fake_OROM.pio = bus.master
|
||||
self.fake_pnp_addr.pio = bus.master
|
||||
self.fake_pnp_write.pio = bus.master
|
||||
self.fake_pnp_read0.pio = bus.master
|
||||
self.fake_pnp_read1.pio = bus.master
|
||||
self.fake_pnp_read2.pio = bus.master
|
||||
self.fake_pnp_read3.pio = bus.master
|
||||
self.fake_pnp_read4.pio = bus.master
|
||||
self.fake_pnp_read5.pio = bus.master
|
||||
self.fake_pnp_read6.pio = bus.master
|
||||
self.fake_pnp_read7.pio = bus.master
|
||||
self.fake_ata0.pio = bus.master
|
||||
self.fake_ata1.pio = bus.master
|
||||
self.fb.pio = bus.master
|
||||
self.io.pio = bus.master
|
||||
self.uart.pio = bus.master
|
||||
self.backdoor.pio = bus.master
|
||||
75
simulators/gem5/src/dev/alpha/access.h
Normal file
75
simulators/gem5/src/dev/alpha/access.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
#ifndef __ALPHA_ACCESS_H__
|
||||
#define __ALPHA_ACCESS_H__
|
||||
|
||||
/** @file
|
||||
* System Console Memory Mapped Register Definition
|
||||
*/
|
||||
|
||||
#define ALPHA_ACCESS_VERSION (1305)
|
||||
|
||||
#ifdef CONSOLE
|
||||
typedef unsigned uint32_t;
|
||||
typedef unsigned long uint64_t;
|
||||
#endif
|
||||
|
||||
// This structure hacked up from simos
|
||||
struct AlphaAccess
|
||||
{
|
||||
uint32_t last_offset; // 00: must be first field
|
||||
uint32_t version; // 04:
|
||||
uint32_t numCPUs; // 08:
|
||||
uint32_t intrClockFrequency; // 0C: Hz
|
||||
uint64_t cpuClock; // 10: MHz
|
||||
uint64_t mem_size; // 18:
|
||||
|
||||
// Loaded kernel
|
||||
uint64_t kernStart; // 20:
|
||||
uint64_t kernEnd; // 28:
|
||||
uint64_t entryPoint; // 30:
|
||||
|
||||
// console disk stuff
|
||||
uint64_t diskUnit; // 38:
|
||||
uint64_t diskCount; // 40:
|
||||
uint64_t diskPAddr; // 48:
|
||||
uint64_t diskBlock; // 50:
|
||||
uint64_t diskOperation; // 58:
|
||||
|
||||
// console simple output stuff
|
||||
uint64_t outputChar; // 60: Placeholder for output
|
||||
uint64_t inputChar; // 68: Placeholder for input
|
||||
|
||||
// MP boot
|
||||
uint64_t cpuStack[64]; // 70:
|
||||
};
|
||||
|
||||
#endif // __ALPHA_ACCESS_H__
|
||||
317
simulators/gem5/src/dev/alpha/backdoor.cc
Normal file
317
simulators/gem5/src/dev/alpha/backdoor.cc
Normal file
@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2005 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: Nathan Binkert
|
||||
* Ali Saidi
|
||||
* Steve Reinhardt
|
||||
* Erik Hallnor
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Alpha Console Backdoor Definition
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
#include "arch/alpha/system.hh"
|
||||
#include "base/inifile.hh"
|
||||
#include "base/str.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "debug/AlphaBackdoor.hh"
|
||||
#include "dev/alpha/backdoor.hh"
|
||||
#include "dev/alpha/tsunami.hh"
|
||||
#include "dev/alpha/tsunami_cchip.hh"
|
||||
#include "dev/alpha/tsunami_io.hh"
|
||||
#include "dev/platform.hh"
|
||||
#include "dev/simple_disk.hh"
|
||||
#include "dev/terminal.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "mem/physical.hh"
|
||||
#include "params/AlphaBackdoor.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlphaISA;
|
||||
|
||||
AlphaBackdoor::AlphaBackdoor(const Params *p)
|
||||
: BasicPioDevice(p), disk(p->disk), terminal(p->terminal),
|
||||
system(p->system), cpu(p->cpu)
|
||||
{
|
||||
|
||||
pioSize = sizeof(struct AlphaAccess);
|
||||
|
||||
alphaAccess = new Access();
|
||||
alphaAccess->last_offset = pioSize - 1;
|
||||
|
||||
alphaAccess->version = ALPHA_ACCESS_VERSION;
|
||||
alphaAccess->diskUnit = 1;
|
||||
|
||||
alphaAccess->diskCount = 0;
|
||||
alphaAccess->diskPAddr = 0;
|
||||
alphaAccess->diskBlock = 0;
|
||||
alphaAccess->diskOperation = 0;
|
||||
alphaAccess->outputChar = 0;
|
||||
alphaAccess->inputChar = 0;
|
||||
std::memset(alphaAccess->cpuStack, 0, sizeof(alphaAccess->cpuStack));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
AlphaBackdoor::startup()
|
||||
{
|
||||
system->setAlphaAccess(pioAddr);
|
||||
alphaAccess->numCPUs = system->numContexts();
|
||||
alphaAccess->kernStart = system->getKernelStart();
|
||||
alphaAccess->kernEnd = system->getKernelEnd();
|
||||
alphaAccess->entryPoint = system->getKernelEntry();
|
||||
alphaAccess->mem_size = system->memSize();
|
||||
alphaAccess->cpuClock = cpu->frequency() / 1000000; // In MHz
|
||||
Tsunami *tsunami = dynamic_cast<Tsunami *>(params()->platform);
|
||||
if (!tsunami)
|
||||
fatal("Platform is not Tsunami.\n");
|
||||
alphaAccess->intrClockFrequency = tsunami->io->frequency();
|
||||
}
|
||||
|
||||
Tick
|
||||
AlphaBackdoor::read(PacketPtr pkt)
|
||||
{
|
||||
|
||||
/** XXX Do we want to push the addr munging to a bus brige or something? So
|
||||
* the device has it's physical address and then the bridge adds on whatever
|
||||
* machine dependent address swizzle is required?
|
||||
*/
|
||||
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
pkt->allocate();
|
||||
pkt->makeAtomicResponse();
|
||||
|
||||
switch (pkt->getSize())
|
||||
{
|
||||
case sizeof(uint32_t):
|
||||
switch (daddr)
|
||||
{
|
||||
case offsetof(AlphaAccess, last_offset):
|
||||
pkt->set(alphaAccess->last_offset);
|
||||
break;
|
||||
case offsetof(AlphaAccess, version):
|
||||
pkt->set(alphaAccess->version);
|
||||
break;
|
||||
case offsetof(AlphaAccess, numCPUs):
|
||||
pkt->set(alphaAccess->numCPUs);
|
||||
break;
|
||||
case offsetof(AlphaAccess, intrClockFrequency):
|
||||
pkt->set(alphaAccess->intrClockFrequency);
|
||||
break;
|
||||
default:
|
||||
/* Old console code read in everyting as a 32bit int
|
||||
* we now break that for better error checking.
|
||||
*/
|
||||
pkt->setBadAddress();
|
||||
}
|
||||
DPRINTF(AlphaBackdoor, "read: offset=%#x val=%#x\n", daddr,
|
||||
pkt->get<uint32_t>());
|
||||
break;
|
||||
case sizeof(uint64_t):
|
||||
switch (daddr)
|
||||
{
|
||||
case offsetof(AlphaAccess, inputChar):
|
||||
pkt->set(terminal->console_in());
|
||||
break;
|
||||
case offsetof(AlphaAccess, cpuClock):
|
||||
pkt->set(alphaAccess->cpuClock);
|
||||
break;
|
||||
case offsetof(AlphaAccess, mem_size):
|
||||
pkt->set(alphaAccess->mem_size);
|
||||
break;
|
||||
case offsetof(AlphaAccess, kernStart):
|
||||
pkt->set(alphaAccess->kernStart);
|
||||
break;
|
||||
case offsetof(AlphaAccess, kernEnd):
|
||||
pkt->set(alphaAccess->kernEnd);
|
||||
break;
|
||||
case offsetof(AlphaAccess, entryPoint):
|
||||
pkt->set(alphaAccess->entryPoint);
|
||||
break;
|
||||
case offsetof(AlphaAccess, diskUnit):
|
||||
pkt->set(alphaAccess->diskUnit);
|
||||
break;
|
||||
case offsetof(AlphaAccess, diskCount):
|
||||
pkt->set(alphaAccess->diskCount);
|
||||
break;
|
||||
case offsetof(AlphaAccess, diskPAddr):
|
||||
pkt->set(alphaAccess->diskPAddr);
|
||||
break;
|
||||
case offsetof(AlphaAccess, diskBlock):
|
||||
pkt->set(alphaAccess->diskBlock);
|
||||
break;
|
||||
case offsetof(AlphaAccess, diskOperation):
|
||||
pkt->set(alphaAccess->diskOperation);
|
||||
break;
|
||||
case offsetof(AlphaAccess, outputChar):
|
||||
pkt->set(alphaAccess->outputChar);
|
||||
break;
|
||||
default:
|
||||
int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
|
||||
sizeof(alphaAccess->cpuStack[0]);
|
||||
|
||||
if (cpunum >= 0 && cpunum < 64)
|
||||
pkt->set(alphaAccess->cpuStack[cpunum]);
|
||||
else
|
||||
panic("Unknown 64bit access, %#x\n", daddr);
|
||||
}
|
||||
DPRINTF(AlphaBackdoor, "read: offset=%#x val=%#x\n", daddr,
|
||||
pkt->get<uint64_t>());
|
||||
break;
|
||||
default:
|
||||
pkt->setBadAddress();
|
||||
}
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
AlphaBackdoor::write(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
uint64_t val = pkt->get<uint64_t>();
|
||||
assert(pkt->getSize() == sizeof(uint64_t));
|
||||
|
||||
switch (daddr) {
|
||||
case offsetof(AlphaAccess, diskUnit):
|
||||
alphaAccess->diskUnit = val;
|
||||
break;
|
||||
|
||||
case offsetof(AlphaAccess, diskCount):
|
||||
alphaAccess->diskCount = val;
|
||||
break;
|
||||
|
||||
case offsetof(AlphaAccess, diskPAddr):
|
||||
alphaAccess->diskPAddr = val;
|
||||
break;
|
||||
|
||||
case offsetof(AlphaAccess, diskBlock):
|
||||
alphaAccess->diskBlock = val;
|
||||
break;
|
||||
|
||||
case offsetof(AlphaAccess, diskOperation):
|
||||
if (val == 0x13)
|
||||
disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock,
|
||||
alphaAccess->diskCount);
|
||||
else
|
||||
panic("Invalid disk operation!");
|
||||
|
||||
break;
|
||||
|
||||
case offsetof(AlphaAccess, outputChar):
|
||||
terminal->out((char)(val & 0xff));
|
||||
break;
|
||||
|
||||
default:
|
||||
int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
|
||||
sizeof(alphaAccess->cpuStack[0]);
|
||||
inform("Launching CPU %d @ %d", cpunum, curTick());
|
||||
assert(val > 0 && "Must not access primary cpu");
|
||||
if (cpunum >= 0 && cpunum < 64)
|
||||
alphaAccess->cpuStack[cpunum] = val;
|
||||
else
|
||||
panic("Unknown 64bit access, %#x\n", daddr);
|
||||
}
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
AlphaBackdoor::Access::serialize(ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(last_offset);
|
||||
SERIALIZE_SCALAR(version);
|
||||
SERIALIZE_SCALAR(numCPUs);
|
||||
SERIALIZE_SCALAR(mem_size);
|
||||
SERIALIZE_SCALAR(cpuClock);
|
||||
SERIALIZE_SCALAR(intrClockFrequency);
|
||||
SERIALIZE_SCALAR(kernStart);
|
||||
SERIALIZE_SCALAR(kernEnd);
|
||||
SERIALIZE_SCALAR(entryPoint);
|
||||
SERIALIZE_SCALAR(diskUnit);
|
||||
SERIALIZE_SCALAR(diskCount);
|
||||
SERIALIZE_SCALAR(diskPAddr);
|
||||
SERIALIZE_SCALAR(diskBlock);
|
||||
SERIALIZE_SCALAR(diskOperation);
|
||||
SERIALIZE_SCALAR(outputChar);
|
||||
SERIALIZE_SCALAR(inputChar);
|
||||
SERIALIZE_ARRAY(cpuStack,64);
|
||||
}
|
||||
|
||||
void
|
||||
AlphaBackdoor::Access::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(last_offset);
|
||||
UNSERIALIZE_SCALAR(version);
|
||||
UNSERIALIZE_SCALAR(numCPUs);
|
||||
UNSERIALIZE_SCALAR(mem_size);
|
||||
UNSERIALIZE_SCALAR(cpuClock);
|
||||
UNSERIALIZE_SCALAR(intrClockFrequency);
|
||||
UNSERIALIZE_SCALAR(kernStart);
|
||||
UNSERIALIZE_SCALAR(kernEnd);
|
||||
UNSERIALIZE_SCALAR(entryPoint);
|
||||
UNSERIALIZE_SCALAR(diskUnit);
|
||||
UNSERIALIZE_SCALAR(diskCount);
|
||||
UNSERIALIZE_SCALAR(diskPAddr);
|
||||
UNSERIALIZE_SCALAR(diskBlock);
|
||||
UNSERIALIZE_SCALAR(diskOperation);
|
||||
UNSERIALIZE_SCALAR(outputChar);
|
||||
UNSERIALIZE_SCALAR(inputChar);
|
||||
UNSERIALIZE_ARRAY(cpuStack, 64);
|
||||
}
|
||||
|
||||
void
|
||||
AlphaBackdoor::serialize(ostream &os)
|
||||
{
|
||||
alphaAccess->serialize(os);
|
||||
}
|
||||
|
||||
void
|
||||
AlphaBackdoor::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
alphaAccess->unserialize(cp, section);
|
||||
}
|
||||
|
||||
AlphaBackdoor *
|
||||
AlphaBackdoorParams::create()
|
||||
{
|
||||
return new AlphaBackdoor(this);
|
||||
}
|
||||
126
simulators/gem5/src/dev/alpha/backdoor.hh
Normal file
126
simulators/gem5/src/dev/alpha/backdoor.hh
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* System Console Backdoor Interface
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ALPHA_BACKDOOR_HH__
|
||||
#define __DEV_ALPHA_BACKDOOR_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "base/types.hh"
|
||||
#include "dev/alpha/access.h"
|
||||
#include "dev/io_device.hh"
|
||||
#include "params/AlphaBackdoor.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
class BaseCPU;
|
||||
class Terminal;
|
||||
class AlphaSystem;
|
||||
class SimpleDisk;
|
||||
|
||||
/**
|
||||
* Memory mapped interface to the system console. This device
|
||||
* represents a shared data region between the OS Kernel and the
|
||||
* System Console Backdoor.
|
||||
*
|
||||
* The system console is a small standalone program that is initially
|
||||
* run when the system boots. It contains the necessary code to
|
||||
* access the boot disk, to read/write from the console, and to pass
|
||||
* boot parameters to the kernel.
|
||||
*
|
||||
* This version of the system console is very different from the one
|
||||
* that would be found in a real system. Many of the functions use
|
||||
* some sort of backdoor to get their job done. For example, reading
|
||||
* from the boot device on a real system would require a minimal
|
||||
* device driver to access the disk controller, but since we have a
|
||||
* simulator here, we are able to bypass the disk controller and
|
||||
* access the disk image directly. There are also some things like
|
||||
* reading the kernel off the disk image into memory that are normally
|
||||
* taken care of by the console that are now taken care of by the
|
||||
* simulator.
|
||||
*
|
||||
* These shortcuts are acceptable since the system console is
|
||||
* primarily used doing boot before the kernel has loaded its device
|
||||
* drivers.
|
||||
*/
|
||||
class AlphaBackdoor : public BasicPioDevice
|
||||
{
|
||||
protected:
|
||||
struct Access : public AlphaAccess
|
||||
{
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
union {
|
||||
Access *alphaAccess;
|
||||
uint8_t *consoleData;
|
||||
};
|
||||
|
||||
/** the disk must be accessed from the console */
|
||||
SimpleDisk *disk;
|
||||
|
||||
/** the system console (the terminal) is accessable from the console */
|
||||
Terminal *terminal;
|
||||
|
||||
/** a pointer to the system we are running in */
|
||||
AlphaSystem *system;
|
||||
|
||||
/** a pointer to the CPU boot cpu */
|
||||
BaseCPU *cpu;
|
||||
|
||||
public:
|
||||
typedef AlphaBackdoorParams Params;
|
||||
AlphaBackdoor(const Params *p);
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
virtual void startup();
|
||||
|
||||
/**
|
||||
* memory mapped reads and writes
|
||||
*/
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* standard serialization routines for checkpointing
|
||||
*/
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
#endif // __DEV_ALPHA_BACKDOOR_HH__
|
||||
132
simulators/gem5/src/dev/alpha/tsunami.cc
Normal file
132
simulators/gem5/src/dev/alpha/tsunami.cc
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Implementation of Tsunami platform.
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "arch/alpha/system.hh"
|
||||
#include "config/the_isa.hh"
|
||||
#include "cpu/intr_control.hh"
|
||||
#include "dev/alpha/tsunami.hh"
|
||||
#include "dev/alpha/tsunami_cchip.hh"
|
||||
#include "dev/alpha/tsunami_io.hh"
|
||||
#include "dev/alpha/tsunami_pchip.hh"
|
||||
#include "dev/terminal.hh"
|
||||
|
||||
using namespace std;
|
||||
//Should this be AlphaISA?
|
||||
using namespace TheISA;
|
||||
|
||||
Tsunami::Tsunami(const Params *p)
|
||||
: Platform(p), system(p->system)
|
||||
{
|
||||
for (int i = 0; i < Tsunami::Max_CPUs; i++)
|
||||
intr_sum_type[i] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Tsunami::init()
|
||||
{
|
||||
AlphaSystem *alphaSystem = dynamic_cast<AlphaSystem *>(system);
|
||||
assert(alphaSystem);
|
||||
alphaSystem->setIntrFreq(io->frequency());
|
||||
}
|
||||
|
||||
void
|
||||
Tsunami::postConsoleInt()
|
||||
{
|
||||
io->postPIC(0x10);
|
||||
}
|
||||
|
||||
void
|
||||
Tsunami::clearConsoleInt()
|
||||
{
|
||||
io->clearPIC(0x10);
|
||||
}
|
||||
|
||||
void
|
||||
Tsunami::postPciInt(int line)
|
||||
{
|
||||
cchip->postDRIR(line);
|
||||
}
|
||||
|
||||
void
|
||||
Tsunami::clearPciInt(int line)
|
||||
{
|
||||
cchip->clearDRIR(line);
|
||||
}
|
||||
|
||||
Addr
|
||||
Tsunami::pciToDma(Addr pciAddr) const
|
||||
{
|
||||
return pchip->translatePciToDma(pciAddr);
|
||||
}
|
||||
|
||||
|
||||
Addr
|
||||
Tsunami::calcPciConfigAddr(int bus, int dev, int func)
|
||||
{
|
||||
return pchip->calcConfigAddr(bus, dev, func);
|
||||
}
|
||||
|
||||
Addr
|
||||
Tsunami::calcPciIOAddr(Addr addr)
|
||||
{
|
||||
return pchip->calcIOAddr(addr);
|
||||
}
|
||||
|
||||
Addr
|
||||
Tsunami::calcPciMemAddr(Addr addr)
|
||||
{
|
||||
return pchip->calcMemAddr(addr);
|
||||
}
|
||||
|
||||
void
|
||||
Tsunami::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs);
|
||||
}
|
||||
|
||||
void
|
||||
Tsunami::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs);
|
||||
}
|
||||
|
||||
Tsunami *
|
||||
TsunamiParams::create()
|
||||
{
|
||||
return new Tsunami(this);
|
||||
}
|
||||
141
simulators/gem5/src/dev/alpha/tsunami.hh
Normal file
141
simulators/gem5/src/dev/alpha/tsunami.hh
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Declaration of top level class for the Tsunami chipset. This class just
|
||||
* retains pointers to all its children so the children can communicate.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_TSUNAMI_HH__
|
||||
#define __DEV_TSUNAMI_HH__
|
||||
|
||||
#include "dev/platform.hh"
|
||||
#include "params/Tsunami.hh"
|
||||
|
||||
class IdeController;
|
||||
class TsunamiCChip;
|
||||
class TsunamiPChip;
|
||||
class TsunamiIO;
|
||||
class System;
|
||||
|
||||
/**
|
||||
* Top level class for Tsunami Chipset emulation.
|
||||
* This structure just contains pointers to all the
|
||||
* children so the children can commnicate to do the
|
||||
* read work
|
||||
*/
|
||||
|
||||
class Tsunami : public Platform
|
||||
{
|
||||
public:
|
||||
/** Max number of CPUs in a Tsunami */
|
||||
static const int Max_CPUs = 64;
|
||||
|
||||
/** Pointer to the system */
|
||||
System *system;
|
||||
|
||||
/** Pointer to the TsunamiIO device which has the RTC */
|
||||
TsunamiIO *io;
|
||||
|
||||
/** Pointer to the Tsunami CChip.
|
||||
* The chip contains some configuration information and
|
||||
* all the interrupt mask and status registers
|
||||
*/
|
||||
TsunamiCChip *cchip;
|
||||
|
||||
/** Pointer to the Tsunami PChip.
|
||||
* The pchip is the interface to the PCI bus, in our case
|
||||
* it does not have to do much.
|
||||
*/
|
||||
TsunamiPChip *pchip;
|
||||
|
||||
int intr_sum_type[Tsunami::Max_CPUs];
|
||||
int ipi_pending[Tsunami::Max_CPUs];
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
typedef TsunamiParams Params;
|
||||
Tsunami(const Params *p);
|
||||
|
||||
/**
|
||||
* Cause the cpu to post a serial interrupt to the CPU.
|
||||
*/
|
||||
virtual void postConsoleInt();
|
||||
|
||||
/**
|
||||
* Clear a posted CPU interrupt (id=55)
|
||||
*/
|
||||
virtual void clearConsoleInt();
|
||||
|
||||
/**
|
||||
* Cause the chipset to post a cpi interrupt to the CPU.
|
||||
*/
|
||||
virtual void postPciInt(int line);
|
||||
|
||||
/**
|
||||
* Clear a posted PCI->CPU interrupt
|
||||
*/
|
||||
virtual void clearPciInt(int line);
|
||||
|
||||
|
||||
virtual Addr pciToDma(Addr pciAddr) const;
|
||||
|
||||
/**
|
||||
* Calculate the configuration address given a bus/dev/func.
|
||||
*/
|
||||
virtual Addr calcPciConfigAddr(int bus, int dev, int func);
|
||||
|
||||
/**
|
||||
* Calculate the address for an IO location on the PCI bus.
|
||||
*/
|
||||
virtual Addr calcPciIOAddr(Addr addr);
|
||||
|
||||
/**
|
||||
* Calculate the address for a memory location on the PCI bus.
|
||||
*/
|
||||
virtual Addr calcPciMemAddr(Addr addr);
|
||||
|
||||
/**
|
||||
* Serialize this object to the given output stream.
|
||||
* @param os The stream to serialize to.
|
||||
*/
|
||||
virtual void serialize(std::ostream &os);
|
||||
|
||||
/**
|
||||
* Reconstruct the state of this object from a checkpoint.
|
||||
* @param cp The checkpoint use.
|
||||
* @param section The section name of this object
|
||||
*/
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
#endif // __DEV_TSUNAMI_HH__
|
||||
536
simulators/gem5/src/dev/alpha/tsunami_cchip.cc
Normal file
536
simulators/gem5/src/dev/alpha/tsunami_cchip.cc
Normal file
@ -0,0 +1,536 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Ron Dreslinski
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Emulation of the Tsunami CChip CSRs
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "arch/alpha/ev5.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "config/the_isa.hh"
|
||||
#include "cpu/intr_control.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "debug/IPI.hh"
|
||||
#include "debug/Tsunami.hh"
|
||||
#include "dev/alpha/tsunami.hh"
|
||||
#include "dev/alpha/tsunami_cchip.hh"
|
||||
#include "dev/alpha/tsunamireg.h"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "mem/port.hh"
|
||||
#include "params/TsunamiCChip.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
//Should this be AlphaISA?
|
||||
using namespace TheISA;
|
||||
|
||||
TsunamiCChip::TsunamiCChip(const Params *p)
|
||||
: BasicPioDevice(p), tsunami(p->tsunami)
|
||||
{
|
||||
pioSize = 0x10000000;
|
||||
|
||||
drir = 0;
|
||||
ipint = 0;
|
||||
itint = 0;
|
||||
|
||||
for (int x = 0; x < Tsunami::Max_CPUs; x++)
|
||||
{
|
||||
dim[x] = 0;
|
||||
dir[x] = 0;
|
||||
}
|
||||
|
||||
//Put back pointer in tsunami
|
||||
tsunami->cchip = this;
|
||||
}
|
||||
|
||||
Tick
|
||||
TsunamiCChip::read(PacketPtr pkt)
|
||||
{
|
||||
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
|
||||
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr regnum = (pkt->getAddr() - pioAddr) >> 6;
|
||||
Addr daddr = (pkt->getAddr() - pioAddr);
|
||||
|
||||
pkt->allocate();
|
||||
switch (pkt->getSize()) {
|
||||
|
||||
case sizeof(uint64_t):
|
||||
pkt->set<uint64_t>(0);
|
||||
|
||||
if (daddr & TSDEV_CC_BDIMS)
|
||||
{
|
||||
pkt->set(dim[(daddr >> 4) & 0x3F]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (daddr & TSDEV_CC_BDIRS)
|
||||
{
|
||||
pkt->set(dir[(daddr >> 4) & 0x3F]);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(regnum) {
|
||||
case TSDEV_CC_CSR:
|
||||
pkt->set(0x0);
|
||||
break;
|
||||
case TSDEV_CC_MTR:
|
||||
panic("TSDEV_CC_MTR not implemeted\n");
|
||||
break;
|
||||
case TSDEV_CC_MISC:
|
||||
pkt->set(((ipint << 8) & 0xF) | ((itint << 4) & 0xF) |
|
||||
(pkt->req->contextId() & 0x3));
|
||||
// currently, FS cannot handle MT so contextId and
|
||||
// cpuId are effectively the same, don't know if it will
|
||||
// matter if FS becomes MT enabled. I suspect no because
|
||||
// we are currently able to boot up to 64 procs anyway
|
||||
// which would render the CPUID of this register useless
|
||||
// anyway
|
||||
break;
|
||||
case TSDEV_CC_AAR0:
|
||||
case TSDEV_CC_AAR1:
|
||||
case TSDEV_CC_AAR2:
|
||||
case TSDEV_CC_AAR3:
|
||||
pkt->set(0);
|
||||
break;
|
||||
case TSDEV_CC_DIM0:
|
||||
pkt->set(dim[0]);
|
||||
break;
|
||||
case TSDEV_CC_DIM1:
|
||||
pkt->set(dim[1]);
|
||||
break;
|
||||
case TSDEV_CC_DIM2:
|
||||
pkt->set(dim[2]);
|
||||
break;
|
||||
case TSDEV_CC_DIM3:
|
||||
pkt->set(dim[3]);
|
||||
break;
|
||||
case TSDEV_CC_DIR0:
|
||||
pkt->set(dir[0]);
|
||||
break;
|
||||
case TSDEV_CC_DIR1:
|
||||
pkt->set(dir[1]);
|
||||
break;
|
||||
case TSDEV_CC_DIR2:
|
||||
pkt->set(dir[2]);
|
||||
break;
|
||||
case TSDEV_CC_DIR3:
|
||||
pkt->set(dir[3]);
|
||||
break;
|
||||
case TSDEV_CC_DRIR:
|
||||
pkt->set(drir);
|
||||
break;
|
||||
case TSDEV_CC_PRBEN:
|
||||
panic("TSDEV_CC_PRBEN not implemented\n");
|
||||
break;
|
||||
case TSDEV_CC_IIC0:
|
||||
case TSDEV_CC_IIC1:
|
||||
case TSDEV_CC_IIC2:
|
||||
case TSDEV_CC_IIC3:
|
||||
panic("TSDEV_CC_IICx not implemented\n");
|
||||
break;
|
||||
case TSDEV_CC_MPR0:
|
||||
case TSDEV_CC_MPR1:
|
||||
case TSDEV_CC_MPR2:
|
||||
case TSDEV_CC_MPR3:
|
||||
panic("TSDEV_CC_MPRx not implemented\n");
|
||||
break;
|
||||
case TSDEV_CC_IPIR:
|
||||
pkt->set(ipint);
|
||||
break;
|
||||
case TSDEV_CC_ITIR:
|
||||
pkt->set(itint);
|
||||
break;
|
||||
default:
|
||||
panic("default in cchip read reached, accessing 0x%x\n");
|
||||
} // uint64_t
|
||||
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
case sizeof(uint16_t):
|
||||
case sizeof(uint8_t):
|
||||
default:
|
||||
panic("invalid access size(?) for tsunami register!\n");
|
||||
}
|
||||
DPRINTF(Tsunami, "Tsunami CChip: read regnum=%#x size=%d data=%lld\n",
|
||||
regnum, pkt->getSize(), pkt->get<uint64_t>());
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
TsunamiCChip::write(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
Addr regnum = (pkt->getAddr() - pioAddr) >> 6 ;
|
||||
|
||||
|
||||
assert(pkt->getSize() == sizeof(uint64_t));
|
||||
|
||||
DPRINTF(Tsunami, "write - addr=%#x value=%#x\n", pkt->getAddr(), pkt->get<uint64_t>());
|
||||
|
||||
bool supportedWrite = false;
|
||||
|
||||
|
||||
if (daddr & TSDEV_CC_BDIMS)
|
||||
{
|
||||
int number = (daddr >> 4) & 0x3F;
|
||||
|
||||
uint64_t bitvector;
|
||||
uint64_t olddim;
|
||||
uint64_t olddir;
|
||||
|
||||
olddim = dim[number];
|
||||
olddir = dir[number];
|
||||
dim[number] = pkt->get<uint64_t>();
|
||||
dir[number] = dim[number] & drir;
|
||||
for(int x = 0; x < Tsunami::Max_CPUs; x++)
|
||||
{
|
||||
bitvector = ULL(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, "dim write resulting in posting dir"
|
||||
" interrupt to cpu %d\n", number);
|
||||
}
|
||||
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 %d\n", number);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch(regnum) {
|
||||
case TSDEV_CC_CSR:
|
||||
panic("TSDEV_CC_CSR write\n");
|
||||
case TSDEV_CC_MTR:
|
||||
panic("TSDEV_CC_MTR write not implemented\n");
|
||||
case TSDEV_CC_MISC:
|
||||
uint64_t ipreq;
|
||||
ipreq = (pkt->get<uint64_t>() >> 12) & 0xF;
|
||||
//If it is bit 12-15, this is an IPI post
|
||||
if (ipreq) {
|
||||
reqIPI(ipreq);
|
||||
supportedWrite = true;
|
||||
}
|
||||
|
||||
//If it is bit 8-11, this is an IPI clear
|
||||
uint64_t ipintr;
|
||||
ipintr = (pkt->get<uint64_t>() >> 8) & 0xF;
|
||||
if (ipintr) {
|
||||
clearIPI(ipintr);
|
||||
supportedWrite = true;
|
||||
}
|
||||
|
||||
//If it is the 4-7th bit, clear the RTC interrupt
|
||||
uint64_t itintr;
|
||||
itintr = (pkt->get<uint64_t>() >> 4) & 0xF;
|
||||
if (itintr) {
|
||||
clearITI(itintr);
|
||||
supportedWrite = true;
|
||||
}
|
||||
|
||||
// ignore NXMs
|
||||
if (pkt->get<uint64_t>() & 0x10000000)
|
||||
supportedWrite = true;
|
||||
|
||||
if(!supportedWrite)
|
||||
panic("TSDEV_CC_MISC write not implemented\n");
|
||||
|
||||
break;
|
||||
case TSDEV_CC_AAR0:
|
||||
case TSDEV_CC_AAR1:
|
||||
case TSDEV_CC_AAR2:
|
||||
case TSDEV_CC_AAR3:
|
||||
panic("TSDEV_CC_AARx write not implemeted\n");
|
||||
case TSDEV_CC_DIM0:
|
||||
case TSDEV_CC_DIM1:
|
||||
case TSDEV_CC_DIM2:
|
||||
case TSDEV_CC_DIM3:
|
||||
int number;
|
||||
if(regnum == TSDEV_CC_DIM0)
|
||||
number = 0;
|
||||
else if(regnum == TSDEV_CC_DIM1)
|
||||
number = 1;
|
||||
else if(regnum == 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] = pkt->get<uint64_t>();
|
||||
dir[number] = dim[number] & drir;
|
||||
for(int x = 0; x < 64; x++)
|
||||
{
|
||||
bitvector = ULL(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 %d\n",
|
||||
x);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TSDEV_CC_DIR0:
|
||||
case TSDEV_CC_DIR1:
|
||||
case TSDEV_CC_DIR2:
|
||||
case TSDEV_CC_DIR3:
|
||||
panic("TSDEV_CC_DIR write not implemented\n");
|
||||
case TSDEV_CC_DRIR:
|
||||
panic("TSDEV_CC_DRIR write not implemented\n");
|
||||
case TSDEV_CC_PRBEN:
|
||||
panic("TSDEV_CC_PRBEN write not implemented\n");
|
||||
case TSDEV_CC_IIC0:
|
||||
case TSDEV_CC_IIC1:
|
||||
case TSDEV_CC_IIC2:
|
||||
case TSDEV_CC_IIC3:
|
||||
panic("TSDEV_CC_IICx write not implemented\n");
|
||||
case TSDEV_CC_MPR0:
|
||||
case TSDEV_CC_MPR1:
|
||||
case TSDEV_CC_MPR2:
|
||||
case TSDEV_CC_MPR3:
|
||||
panic("TSDEV_CC_MPRx write not implemented\n");
|
||||
case TSDEV_CC_IPIR:
|
||||
clearIPI(pkt->get<uint64_t>());
|
||||
break;
|
||||
case TSDEV_CC_ITIR:
|
||||
clearITI(pkt->get<uint64_t>());
|
||||
break;
|
||||
case TSDEV_CC_IPIQ:
|
||||
reqIPI(pkt->get<uint64_t>());
|
||||
break;
|
||||
default:
|
||||
panic("default in cchip read reached, accessing 0x%x\n");
|
||||
} // swtich(regnum)
|
||||
} // not BIG_TSUNAMI write
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiCChip::clearIPI(uint64_t ipintr)
|
||||
{
|
||||
int numcpus = sys->threadContexts.size();
|
||||
assert(numcpus <= Tsunami::Max_CPUs);
|
||||
|
||||
if (ipintr) {
|
||||
for (int cpunum=0; cpunum < numcpus; cpunum++) {
|
||||
// Check each cpu bit
|
||||
uint64_t cpumask = ULL(1) << cpunum;
|
||||
if (ipintr & cpumask) {
|
||||
// Check if there is a pending ipi
|
||||
if (ipint & cpumask) {
|
||||
ipint &= ~cpumask;
|
||||
tsunami->intrctrl->clear(cpunum, TheISA::INTLEVEL_IRQ3, 0);
|
||||
DPRINTF(IPI, "clear IPI IPI cpu=%d\n", cpunum);
|
||||
}
|
||||
else
|
||||
warn("clear IPI for CPU=%d, but NO IPI\n", cpunum);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
panic("Big IPI Clear, but not processors indicated\n");
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiCChip::clearITI(uint64_t itintr)
|
||||
{
|
||||
int numcpus = sys->threadContexts.size();
|
||||
assert(numcpus <= Tsunami::Max_CPUs);
|
||||
|
||||
if (itintr) {
|
||||
for (int i=0; i < numcpus; i++) {
|
||||
uint64_t cpumask = ULL(1) << i;
|
||||
if (itintr & cpumask & itint) {
|
||||
tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
|
||||
itint &= ~cpumask;
|
||||
DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
panic("Big ITI Clear, but not processors indicated\n");
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiCChip::reqIPI(uint64_t ipreq)
|
||||
{
|
||||
int numcpus = sys->threadContexts.size();
|
||||
assert(numcpus <= Tsunami::Max_CPUs);
|
||||
|
||||
if (ipreq) {
|
||||
for (int cpunum=0; cpunum < numcpus; cpunum++) {
|
||||
// Check each cpu bit
|
||||
uint64_t cpumask = ULL(1) << cpunum;
|
||||
if (ipreq & cpumask) {
|
||||
// Check if there is already an ipi (bits 8:11)
|
||||
if (!(ipint & cpumask)) {
|
||||
ipint |= cpumask;
|
||||
tsunami->intrctrl->post(cpunum, TheISA::INTLEVEL_IRQ3, 0);
|
||||
DPRINTF(IPI, "send IPI cpu=%d\n", cpunum);
|
||||
}
|
||||
else
|
||||
warn("post IPI for CPU=%d, but IPI already\n", cpunum);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
panic("Big IPI Request, but not processors indicated\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TsunamiCChip::postRTC()
|
||||
{
|
||||
int size = sys->threadContexts.size();
|
||||
assert(size <= Tsunami::Max_CPUs);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
uint64_t cpumask = ULL(1) << i;
|
||||
if (!(cpumask & itint)) {
|
||||
itint |= cpumask;
|
||||
tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0);
|
||||
DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiCChip::postDRIR(uint32_t interrupt)
|
||||
{
|
||||
uint64_t bitvector = ULL(1) << interrupt;
|
||||
uint64_t size = sys->threadContexts.size();
|
||||
assert(size <= Tsunami::Max_CPUs);
|
||||
drir |= bitvector;
|
||||
|
||||
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(uint32_t interrupt)
|
||||
{
|
||||
uint64_t bitvector = ULL(1) << interrupt;
|
||||
uint64_t size = sys->threadContexts.size();
|
||||
assert(size <= Tsunami::Max_CPUs);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TsunamiCChip::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
|
||||
SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
|
||||
SERIALIZE_SCALAR(ipint);
|
||||
SERIALIZE_SCALAR(itint);
|
||||
SERIALIZE_SCALAR(drir);
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiCChip::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
|
||||
UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
|
||||
UNSERIALIZE_SCALAR(ipint);
|
||||
UNSERIALIZE_SCALAR(itint);
|
||||
UNSERIALIZE_SCALAR(drir);
|
||||
}
|
||||
|
||||
TsunamiCChip *
|
||||
TsunamiCChipParams::create()
|
||||
{
|
||||
return new TsunamiCChip(this);
|
||||
}
|
||||
151
simulators/gem5/src/dev/alpha/tsunami_cchip.hh
Normal file
151
simulators/gem5/src/dev/alpha/tsunami_cchip.hh
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Emulation of the Tsunami CChip CSRs
|
||||
*/
|
||||
|
||||
#ifndef __TSUNAMI_CCHIP_HH__
|
||||
#define __TSUNAMI_CCHIP_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/alpha/tsunami.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "params/TsunamiCChip.hh"
|
||||
|
||||
/**
|
||||
* Tsunami CChip CSR Emulation. This device includes all the interrupt
|
||||
* handling code for the chipset.
|
||||
*/
|
||||
class TsunamiCChip : public BasicPioDevice
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* pointer to the tsunami object.
|
||||
* This is our access to all the other tsunami
|
||||
* devices.
|
||||
*/
|
||||
Tsunami *tsunami;
|
||||
|
||||
/**
|
||||
* The dims are device interrupt mask registers.
|
||||
* One exists for each CPU, the DRIR X DIM = DIR
|
||||
*/
|
||||
uint64_t dim[Tsunami::Max_CPUs];
|
||||
|
||||
/**
|
||||
* The dirs are device interrupt registers.
|
||||
* One exists for each CPU, the DRIR X DIM = DIR
|
||||
*/
|
||||
uint64_t dir[Tsunami::Max_CPUs];
|
||||
|
||||
/**
|
||||
* This register contains bits for each PCI interrupt
|
||||
* that can occur.
|
||||
*/
|
||||
uint64_t drir;
|
||||
|
||||
/** Indicator of which CPUs have an IPI interrupt */
|
||||
uint64_t ipint;
|
||||
|
||||
/** Indicator of which CPUs have an RTC interrupt */
|
||||
uint64_t itint;
|
||||
|
||||
public:
|
||||
typedef TsunamiCChipParams Params;
|
||||
/**
|
||||
* Initialize the Tsunami CChip by setting all of the
|
||||
* device register to 0.
|
||||
* @param p params struct
|
||||
*/
|
||||
TsunamiCChip(const Params *p);
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* post an RTC interrupt to the CPU
|
||||
*/
|
||||
void postRTC();
|
||||
|
||||
/**
|
||||
* post an interrupt to the CPU.
|
||||
* @param interrupt the interrupt number to post (0-64)
|
||||
*/
|
||||
void postDRIR(uint32_t interrupt);
|
||||
|
||||
/**
|
||||
* clear an interrupt previously posted to the CPU.
|
||||
* @param interrupt the interrupt number to post (0-64)
|
||||
*/
|
||||
void clearDRIR(uint32_t interrupt);
|
||||
|
||||
/**
|
||||
* post an ipi interrupt to the CPU.
|
||||
* @param ipintr the cpu number to clear(bitvector)
|
||||
*/
|
||||
void clearIPI(uint64_t ipintr);
|
||||
|
||||
/**
|
||||
* clear a timer interrupt previously posted to the CPU.
|
||||
* @param itintr the cpu number to clear(bitvector)
|
||||
*/
|
||||
void clearITI(uint64_t itintr);
|
||||
|
||||
/**
|
||||
* request an interrupt be posted to the CPU.
|
||||
* @param ipreq the cpu number to interrupt(bitvector)
|
||||
*/
|
||||
void reqIPI(uint64_t ipreq);
|
||||
|
||||
|
||||
/**
|
||||
* Serialize this object to the given output stream.
|
||||
* @param os The stream to serialize to.
|
||||
*/
|
||||
virtual void serialize(std::ostream &os);
|
||||
|
||||
/**
|
||||
* Reconstruct the state of this object from a checkpoint.
|
||||
* @param cp The checkpoint use.
|
||||
* @param section The section name of this object
|
||||
*/
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
};
|
||||
|
||||
#endif // __TSUNAMI_CCHIP_HH__
|
||||
295
simulators/gem5/src/dev/alpha/tsunami_io.cc
Normal file
295
simulators/gem5/src/dev/alpha/tsunami_io.cc
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Andrew Schultz
|
||||
* Miguel Serrano
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Tsunami I/O including PIC, PIT, RTC, DMA
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/time.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "config/the_isa.hh"
|
||||
#include "debug/Tsunami.hh"
|
||||
#include "dev/alpha/tsunami.hh"
|
||||
#include "dev/alpha/tsunami_cchip.hh"
|
||||
#include "dev/alpha/tsunami_io.hh"
|
||||
#include "dev/alpha/tsunamireg.h"
|
||||
#include "dev/rtcreg.h"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "mem/port.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
// clang complains about std::set being overloaded with Packet::set if
|
||||
// we open up the entire namespace std
|
||||
using std::string;
|
||||
using std::ostream;
|
||||
|
||||
//Should this be AlphaISA?
|
||||
using namespace TheISA;
|
||||
|
||||
TsunamiIO::RTC::RTC(const string &n, const TsunamiIOParams *p)
|
||||
: MC146818(p->tsunami, n, p->time, p->year_is_bcd, p->frequency),
|
||||
tsunami(p->tsunami)
|
||||
{
|
||||
}
|
||||
|
||||
TsunamiIO::TsunamiIO(const Params *p)
|
||||
: BasicPioDevice(p), tsunami(p->tsunami),
|
||||
pitimer(this, p->name + "pitimer"), rtc(p->name + ".rtc", p)
|
||||
{
|
||||
pioSize = 0x100;
|
||||
|
||||
// set the back pointer from tsunami to myself
|
||||
tsunami->io = this;
|
||||
|
||||
timerData = 0;
|
||||
picr = 0;
|
||||
picInterrupting = false;
|
||||
}
|
||||
|
||||
Tick
|
||||
TsunamiIO::frequency() const
|
||||
{
|
||||
return SimClock::Frequency / params()->frequency;
|
||||
}
|
||||
|
||||
Tick
|
||||
TsunamiIO::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(),
|
||||
pkt->getSize(), daddr);
|
||||
|
||||
pkt->allocate();
|
||||
|
||||
if (pkt->getSize() == sizeof(uint8_t)) {
|
||||
switch(daddr) {
|
||||
// PIC1 mask read
|
||||
case TSDEV_PIC1_MASK:
|
||||
pkt->set(~mask1);
|
||||
break;
|
||||
case TSDEV_PIC2_MASK:
|
||||
pkt->set(~mask2);
|
||||
break;
|
||||
case TSDEV_PIC1_ISR:
|
||||
// !!! If this is modified 64bit case needs to be too
|
||||
// Pal code has to do a 64 bit physical read because there is
|
||||
// no load physical byte instruction
|
||||
pkt->set(picr);
|
||||
break;
|
||||
case TSDEV_PIC2_ISR:
|
||||
// PIC2 not implemnted... just return 0
|
||||
pkt->set(0x00);
|
||||
break;
|
||||
case TSDEV_TMR0_DATA:
|
||||
pkt->set(pitimer.readCounter(0));
|
||||
break;
|
||||
case TSDEV_TMR1_DATA:
|
||||
pkt->set(pitimer.readCounter(1));
|
||||
break;
|
||||
case TSDEV_TMR2_DATA:
|
||||
pkt->set(pitimer.readCounter(2));
|
||||
break;
|
||||
case TSDEV_RTC_DATA:
|
||||
pkt->set(rtc.readData(rtcAddr));
|
||||
break;
|
||||
case TSDEV_CTRL_PORTB:
|
||||
if (pitimer.outputHigh(2))
|
||||
pkt->set(PORTB_SPKR_HIGH);
|
||||
else
|
||||
pkt->set(0x00);
|
||||
break;
|
||||
default:
|
||||
panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize());
|
||||
}
|
||||
} else if (pkt->getSize() == sizeof(uint64_t)) {
|
||||
if (daddr == TSDEV_PIC1_ISR)
|
||||
pkt->set<uint64_t>(picr);
|
||||
else
|
||||
panic("I/O Read - invalid addr - va %#x size %d\n",
|
||||
pkt->getAddr(), pkt->getSize());
|
||||
} else {
|
||||
panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize());
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
TsunamiIO::write(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
|
||||
pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>());
|
||||
|
||||
assert(pkt->getSize() == sizeof(uint8_t));
|
||||
|
||||
switch(daddr) {
|
||||
case TSDEV_PIC1_MASK:
|
||||
mask1 = ~(pkt->get<uint8_t>());
|
||||
if ((picr & mask1) && !picInterrupting) {
|
||||
picInterrupting = true;
|
||||
tsunami->cchip->postDRIR(55);
|
||||
DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
|
||||
}
|
||||
if ((!(picr & mask1)) && picInterrupting) {
|
||||
picInterrupting = false;
|
||||
tsunami->cchip->clearDRIR(55);
|
||||
DPRINTF(Tsunami, "clearing pic interrupt\n");
|
||||
}
|
||||
break;
|
||||
case TSDEV_PIC2_MASK:
|
||||
mask2 = pkt->get<uint8_t>();
|
||||
//PIC2 Not implemented to interrupt
|
||||
break;
|
||||
case TSDEV_PIC1_ACK:
|
||||
// clear the interrupt on the PIC
|
||||
picr &= ~(1 << (pkt->get<uint8_t>() & 0xF));
|
||||
if (!(picr & mask1))
|
||||
tsunami->cchip->clearDRIR(55);
|
||||
break;
|
||||
case TSDEV_DMA1_MODE:
|
||||
mode1 = pkt->get<uint8_t>();
|
||||
break;
|
||||
case TSDEV_DMA2_MODE:
|
||||
mode2 = pkt->get<uint8_t>();
|
||||
break;
|
||||
case TSDEV_TMR0_DATA:
|
||||
pitimer.writeCounter(0, pkt->get<uint8_t>());
|
||||
break;
|
||||
case TSDEV_TMR1_DATA:
|
||||
pitimer.writeCounter(1, pkt->get<uint8_t>());
|
||||
break;
|
||||
case TSDEV_TMR2_DATA:
|
||||
pitimer.writeCounter(2, pkt->get<uint8_t>());
|
||||
break;
|
||||
case TSDEV_TMR_CTRL:
|
||||
pitimer.writeControl(pkt->get<uint8_t>());
|
||||
break;
|
||||
case TSDEV_RTC_ADDR:
|
||||
rtcAddr = pkt->get<uint8_t>();
|
||||
break;
|
||||
case TSDEV_RTC_DATA:
|
||||
rtc.writeData(rtcAddr, pkt->get<uint8_t>());
|
||||
break;
|
||||
case TSDEV_KBD:
|
||||
case TSDEV_DMA1_CMND:
|
||||
case TSDEV_DMA2_CMND:
|
||||
case TSDEV_DMA1_MMASK:
|
||||
case TSDEV_DMA2_MMASK:
|
||||
case TSDEV_PIC2_ACK:
|
||||
case TSDEV_DMA1_RESET:
|
||||
case TSDEV_DMA2_RESET:
|
||||
case TSDEV_DMA1_MASK:
|
||||
case TSDEV_DMA2_MASK:
|
||||
case TSDEV_CTRL_PORTB:
|
||||
break;
|
||||
default:
|
||||
panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>());
|
||||
}
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiIO::postPIC(uint8_t bitvector)
|
||||
{
|
||||
//PIC2 Is not implemented, because nothing of interest there
|
||||
picr |= bitvector;
|
||||
if (picr & mask1) {
|
||||
tsunami->cchip->postDRIR(55);
|
||||
DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiIO::clearPIC(uint8_t bitvector)
|
||||
{
|
||||
//PIC2 Is not implemented, because nothing of interest there
|
||||
picr &= ~bitvector;
|
||||
if (!(picr & mask1)) {
|
||||
tsunami->cchip->clearDRIR(55);
|
||||
DPRINTF(Tsunami, "clearing pic interrupt to cchip\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiIO::serialize(ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(rtcAddr);
|
||||
SERIALIZE_SCALAR(timerData);
|
||||
SERIALIZE_SCALAR(mask1);
|
||||
SERIALIZE_SCALAR(mask2);
|
||||
SERIALIZE_SCALAR(mode1);
|
||||
SERIALIZE_SCALAR(mode2);
|
||||
SERIALIZE_SCALAR(picr);
|
||||
SERIALIZE_SCALAR(picInterrupting);
|
||||
|
||||
// Serialize the timers
|
||||
pitimer.serialize("pitimer", os);
|
||||
rtc.serialize("rtc", os);
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiIO::unserialize(Checkpoint *cp, const string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(rtcAddr);
|
||||
UNSERIALIZE_SCALAR(timerData);
|
||||
UNSERIALIZE_SCALAR(mask1);
|
||||
UNSERIALIZE_SCALAR(mask2);
|
||||
UNSERIALIZE_SCALAR(mode1);
|
||||
UNSERIALIZE_SCALAR(mode2);
|
||||
UNSERIALIZE_SCALAR(picr);
|
||||
UNSERIALIZE_SCALAR(picInterrupting);
|
||||
|
||||
// Unserialize the timers
|
||||
pitimer.unserialize("pitimer", cp, section);
|
||||
rtc.unserialize("rtc", cp, section);
|
||||
}
|
||||
|
||||
TsunamiIO *
|
||||
TsunamiIOParams::create()
|
||||
{
|
||||
return new TsunamiIO(this);
|
||||
}
|
||||
158
simulators/gem5/src/dev/alpha/tsunami_io.hh
Normal file
158
simulators/gem5/src/dev/alpha/tsunami_io.hh
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Andrew Schultz
|
||||
* Miguel Serrano
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Tsunami I/O Space mapping including RTC/timer interrupts
|
||||
*/
|
||||
|
||||
#ifndef __DEV_TSUNAMI_IO_HH__
|
||||
#define __DEV_TSUNAMI_IO_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/alpha/tsunami.hh"
|
||||
#include "dev/intel_8254_timer.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "dev/mc146818.hh"
|
||||
#include "params/TsunamiIO.hh"
|
||||
#include "sim/eventq.hh"
|
||||
|
||||
/**
|
||||
* Tsunami I/O device is a catch all for all the south bridge stuff we care
|
||||
* to implement.
|
||||
*/
|
||||
class TsunamiIO : public BasicPioDevice
|
||||
{
|
||||
private:
|
||||
struct tm tm;
|
||||
|
||||
protected:
|
||||
|
||||
class RTC : public MC146818
|
||||
{
|
||||
public:
|
||||
Tsunami *tsunami;
|
||||
RTC(const std::string &n, const TsunamiIOParams *p);
|
||||
|
||||
protected:
|
||||
void handleEvent()
|
||||
{
|
||||
//Actually interrupt the processor here
|
||||
tsunami->cchip->postRTC();
|
||||
}
|
||||
};
|
||||
|
||||
/** Mask of the PIC1 */
|
||||
uint8_t mask1;
|
||||
|
||||
/** Mask of the PIC2 */
|
||||
uint8_t mask2;
|
||||
|
||||
/** Mode of PIC1. Not used for anything */
|
||||
uint8_t mode1;
|
||||
|
||||
/** Mode of PIC2. Not used for anything */
|
||||
uint8_t mode2;
|
||||
|
||||
/** Raw PIC interrupt register before masking */
|
||||
uint8_t picr; //Raw PIC interrput register
|
||||
|
||||
/** Is the pic interrupting right now or not. */
|
||||
bool picInterrupting;
|
||||
|
||||
/** A pointer to the Tsunami device which be belong to */
|
||||
Tsunami *tsunami;
|
||||
|
||||
/** Intel 8253 Periodic Interval Timer */
|
||||
Intel8254Timer pitimer;
|
||||
|
||||
RTC rtc;
|
||||
|
||||
uint8_t rtcAddr;
|
||||
|
||||
/** The interval is set via two writes to the PIT.
|
||||
* This variable contains a flag as to how many writes have happened, and
|
||||
* the time so far.
|
||||
*/
|
||||
uint16_t timerData;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Return the freqency of the RTC
|
||||
* @return interrupt rate of the RTC
|
||||
*/
|
||||
Tick frequency() const;
|
||||
|
||||
public:
|
||||
typedef TsunamiIOParams Params;
|
||||
/**
|
||||
* Initialize all the data for devices supported by Tsunami I/O.
|
||||
* @param p pointer to Params struct
|
||||
*/
|
||||
TsunamiIO(const Params *p);
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* Post an PIC interrupt to the CPU via the CChip
|
||||
* @param bitvector interrupt to post.
|
||||
*/
|
||||
void postPIC(uint8_t bitvector);
|
||||
|
||||
/**
|
||||
* Clear a posted interrupt
|
||||
* @param bitvector interrupt to clear
|
||||
*/
|
||||
void clearPIC(uint8_t bitvector);
|
||||
|
||||
/**
|
||||
* Serialize this object to the given output stream.
|
||||
* @param os The stream to serialize to.
|
||||
*/
|
||||
virtual void serialize(std::ostream &os);
|
||||
|
||||
/**
|
||||
* Reconstruct the state of this object from a checkpoint.
|
||||
* @param cp The checkpoint use.
|
||||
* @param section The section name of this object
|
||||
*/
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
};
|
||||
|
||||
#endif // __DEV_TSUNAMI_IO_HH__
|
||||
352
simulators/gem5/src/dev/alpha/tsunami_pchip.cc
Normal file
352
simulators/gem5/src/dev/alpha/tsunami_pchip.cc
Normal file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Andrew Schultz
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Tsunami PChip (pci)
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "config/the_isa.hh"
|
||||
#include "debug/Tsunami.hh"
|
||||
#include "dev/alpha/tsunami.hh"
|
||||
#include "dev/alpha/tsunami_pchip.hh"
|
||||
#include "dev/alpha/tsunamireg.h"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
using namespace std;
|
||||
//Should this be AlphaISA?
|
||||
using namespace TheISA;
|
||||
|
||||
TsunamiPChip::TsunamiPChip(const Params *p)
|
||||
: BasicPioDevice(p)
|
||||
{
|
||||
pioSize = 0x1000;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
wsba[i] = 0;
|
||||
wsm[i] = 0;
|
||||
tba[i] = 0;
|
||||
}
|
||||
|
||||
// initialize pchip control register
|
||||
pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36);
|
||||
|
||||
//Set back pointer in tsunami
|
||||
p->tsunami->pchip = this;
|
||||
}
|
||||
|
||||
Tick
|
||||
TsunamiPChip::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
pkt->allocate();
|
||||
Addr daddr = (pkt->getAddr() - pioAddr) >> 6;;
|
||||
assert(pkt->getSize() == sizeof(uint64_t));
|
||||
|
||||
|
||||
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
|
||||
|
||||
switch(daddr) {
|
||||
case TSDEV_PC_WSBA0:
|
||||
pkt->set(wsba[0]);
|
||||
break;
|
||||
case TSDEV_PC_WSBA1:
|
||||
pkt->set(wsba[1]);
|
||||
break;
|
||||
case TSDEV_PC_WSBA2:
|
||||
pkt->set(wsba[2]);
|
||||
break;
|
||||
case TSDEV_PC_WSBA3:
|
||||
pkt->set(wsba[3]);
|
||||
break;
|
||||
case TSDEV_PC_WSM0:
|
||||
pkt->set(wsm[0]);
|
||||
break;
|
||||
case TSDEV_PC_WSM1:
|
||||
pkt->set(wsm[1]);
|
||||
break;
|
||||
case TSDEV_PC_WSM2:
|
||||
pkt->set(wsm[2]);
|
||||
break;
|
||||
case TSDEV_PC_WSM3:
|
||||
pkt->set(wsm[3]);
|
||||
break;
|
||||
case TSDEV_PC_TBA0:
|
||||
pkt->set(tba[0]);
|
||||
break;
|
||||
case TSDEV_PC_TBA1:
|
||||
pkt->set(tba[1]);
|
||||
break;
|
||||
case TSDEV_PC_TBA2:
|
||||
pkt->set(tba[2]);
|
||||
break;
|
||||
case TSDEV_PC_TBA3:
|
||||
pkt->set(tba[3]);
|
||||
break;
|
||||
case TSDEV_PC_PCTL:
|
||||
pkt->set(pctl);
|
||||
break;
|
||||
case TSDEV_PC_PLAT:
|
||||
panic("PC_PLAT not implemented\n");
|
||||
case TSDEV_PC_RES:
|
||||
panic("PC_RES not implemented\n");
|
||||
case TSDEV_PC_PERROR:
|
||||
pkt->set((uint64_t)0x00);
|
||||
break;
|
||||
case TSDEV_PC_PERRMASK:
|
||||
pkt->set((uint64_t)0x00);
|
||||
break;
|
||||
case TSDEV_PC_PERRSET:
|
||||
panic("PC_PERRSET not implemented\n");
|
||||
case TSDEV_PC_TLBIV:
|
||||
panic("PC_TLBIV not implemented\n");
|
||||
case TSDEV_PC_TLBIA:
|
||||
pkt->set((uint64_t)0x00); // shouldn't be readable, but linux
|
||||
break;
|
||||
case TSDEV_PC_PMONCTL:
|
||||
panic("PC_PMONCTL not implemented\n");
|
||||
case TSDEV_PC_PMONCNT:
|
||||
panic("PC_PMONCTN not implemented\n");
|
||||
default:
|
||||
panic("Default in PChip Read reached reading 0x%x\n", daddr);
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
|
||||
}
|
||||
|
||||
Tick
|
||||
TsunamiPChip::write(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
Addr daddr = (pkt->getAddr() - pioAddr) >> 6;
|
||||
|
||||
assert(pkt->getSize() == sizeof(uint64_t));
|
||||
|
||||
DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize());
|
||||
|
||||
switch(daddr) {
|
||||
case TSDEV_PC_WSBA0:
|
||||
wsba[0] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_WSBA1:
|
||||
wsba[1] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_WSBA2:
|
||||
wsba[2] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_WSBA3:
|
||||
wsba[3] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_WSM0:
|
||||
wsm[0] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_WSM1:
|
||||
wsm[1] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_WSM2:
|
||||
wsm[2] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_WSM3:
|
||||
wsm[3] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_TBA0:
|
||||
tba[0] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_TBA1:
|
||||
tba[1] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_TBA2:
|
||||
tba[2] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_TBA3:
|
||||
tba[3] = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_PCTL:
|
||||
pctl = pkt->get<uint64_t>();
|
||||
break;
|
||||
case TSDEV_PC_PLAT:
|
||||
panic("PC_PLAT not implemented\n");
|
||||
case TSDEV_PC_RES:
|
||||
panic("PC_RES not implemented\n");
|
||||
case TSDEV_PC_PERROR:
|
||||
break;
|
||||
case TSDEV_PC_PERRMASK:
|
||||
panic("PC_PERRMASK not implemented\n");
|
||||
case TSDEV_PC_PERRSET:
|
||||
panic("PC_PERRSET not implemented\n");
|
||||
case TSDEV_PC_TLBIV:
|
||||
panic("PC_TLBIV not implemented\n");
|
||||
case TSDEV_PC_TLBIA:
|
||||
break; // value ignored, supposted to invalidate SG TLB
|
||||
case TSDEV_PC_PMONCTL:
|
||||
panic("PC_PMONCTL not implemented\n");
|
||||
case TSDEV_PC_PMONCNT:
|
||||
panic("PC_PMONCTN not implemented\n");
|
||||
default:
|
||||
panic("Default in PChip write reached reading 0x%x\n", daddr);
|
||||
|
||||
} // uint64_t
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
#define DMA_ADDR_MASK ULL(0x3ffffffff)
|
||||
|
||||
Addr
|
||||
TsunamiPChip::translatePciToDma(Addr busAddr)
|
||||
{
|
||||
// compare the address to the window base registers
|
||||
uint64_t tbaMask = 0;
|
||||
uint64_t baMask = 0;
|
||||
|
||||
uint64_t windowMask = 0;
|
||||
uint64_t windowBase = 0;
|
||||
|
||||
uint64_t pteEntry = 0;
|
||||
|
||||
Addr pteAddr;
|
||||
Addr dmaAddr;
|
||||
|
||||
#if 0
|
||||
DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n",
|
||||
i, wsba[i], wsm[i]);
|
||||
|
||||
windowBase = wsba[i];
|
||||
windowMask = ~wsm[i] & (ULL(0xfff) << 20);
|
||||
|
||||
if ((busAddr & windowMask) == (windowBase & windowMask)) {
|
||||
DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n",
|
||||
i, windowBase, windowMask, (busAddr & windowMask),
|
||||
(windowBase & windowMask));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
||||
windowBase = wsba[i];
|
||||
windowMask = ~wsm[i] & (ULL(0xfff) << 20);
|
||||
|
||||
if ((busAddr & windowMask) == (windowBase & windowMask)) {
|
||||
|
||||
if (wsba[i] & 0x1) { // see if enabled
|
||||
if (wsba[i] & 0x2) { // see if SG bit is set
|
||||
/** @todo
|
||||
This currently is faked by just doing a direct
|
||||
read from memory, however, to be realistic, this
|
||||
needs to actually do a bus transaction. The process
|
||||
is explained in the tsunami documentation on page
|
||||
10-12 and basically munges the address to look up a
|
||||
PTE from a table in memory and then uses that mapping
|
||||
to create an address for the SG page
|
||||
*/
|
||||
|
||||
tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff));
|
||||
baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
|
||||
pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
|
||||
|
||||
sys->physProxy.readBlob(pteAddr, (uint8_t*)&pteEntry,
|
||||
sizeof(uint64_t));
|
||||
|
||||
dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
|
||||
|
||||
} else {
|
||||
baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff);
|
||||
tbaMask = ~baMask;
|
||||
dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
|
||||
}
|
||||
|
||||
return (dmaAddr & DMA_ADDR_MASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if no match was found, then return the original address
|
||||
return busAddr;
|
||||
}
|
||||
|
||||
Addr
|
||||
TsunamiPChip::calcConfigAddr(int bus, int dev, int func)
|
||||
{
|
||||
assert(func < 8);
|
||||
assert(dev < 32);
|
||||
assert(bus == 0);
|
||||
|
||||
return TsunamiPciBus0Config | (func << 8) | (dev << 11);
|
||||
}
|
||||
|
||||
Addr
|
||||
TsunamiPChip::calcIOAddr(Addr addr)
|
||||
{
|
||||
return TSUNAMI_PCI0_IO + addr;
|
||||
}
|
||||
|
||||
Addr
|
||||
TsunamiPChip::calcMemAddr(Addr addr)
|
||||
{
|
||||
return TSUNAMI_PCI0_MEMORY + addr;
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiPChip::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(pctl);
|
||||
SERIALIZE_ARRAY(wsba, 4);
|
||||
SERIALIZE_ARRAY(wsm, 4);
|
||||
SERIALIZE_ARRAY(tba, 4);
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(pctl);
|
||||
UNSERIALIZE_ARRAY(wsba, 4);
|
||||
UNSERIALIZE_ARRAY(wsm, 4);
|
||||
UNSERIALIZE_ARRAY(tba, 4);
|
||||
}
|
||||
|
||||
|
||||
TsunamiPChip *
|
||||
TsunamiPChipParams::create()
|
||||
{
|
||||
return new TsunamiPChip(this);
|
||||
}
|
||||
107
simulators/gem5/src/dev/alpha/tsunami_pchip.hh
Normal file
107
simulators/gem5/src/dev/alpha/tsunami_pchip.hh
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Tsunami PCI interface CSRs
|
||||
*/
|
||||
|
||||
#ifndef __TSUNAMI_PCHIP_HH__
|
||||
#define __TSUNAMI_PCHIP_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/alpha/tsunami.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "params/TsunamiPChip.hh"
|
||||
|
||||
/**
|
||||
* A very simple implementation of the Tsunami PCI interface chips.
|
||||
*/
|
||||
class TsunamiPChip : public BasicPioDevice
|
||||
{
|
||||
protected:
|
||||
|
||||
static const Addr TsunamiPciBus0Config = ULL(0x801fe000000);
|
||||
|
||||
/** Pchip control register */
|
||||
uint64_t pctl;
|
||||
|
||||
/** Window Base addresses */
|
||||
uint64_t wsba[4];
|
||||
|
||||
/** Window masks */
|
||||
uint64_t wsm[4];
|
||||
|
||||
/** Translated Base Addresses */
|
||||
uint64_t tba[4];
|
||||
|
||||
public:
|
||||
typedef TsunamiPChipParams Params;
|
||||
/**
|
||||
* Register the PChip with the mmu and init all wsba, wsm, and tba to 0
|
||||
* @param p pointer to the parameters struct
|
||||
*/
|
||||
TsunamiPChip(const Params *p);
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a PCI bus address to a memory address for DMA.
|
||||
* @todo Andrew says this needs to be fixed. What's wrong with it?
|
||||
* @param busAddr PCI address to translate.
|
||||
* @return memory system address
|
||||
*/
|
||||
Addr translatePciToDma(Addr busAddr);
|
||||
|
||||
Addr calcConfigAddr(int bus, int dev, int func);
|
||||
Addr calcIOAddr(Addr addr);
|
||||
Addr calcMemAddr(Addr addr);
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* Serialize this object to the given output stream.
|
||||
* @param os The stream to serialize to.
|
||||
*/
|
||||
virtual void serialize(std::ostream &os);
|
||||
|
||||
/**
|
||||
* Reconstruct the state of this object from a checkpoint.
|
||||
* @param cp The checkpoint use.
|
||||
* @param section The section name of this object
|
||||
*/
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
#endif // __TSUNAMI_PCHIP_HH__
|
||||
152
simulators/gem5/src/dev/alpha/tsunamireg.h
Normal file
152
simulators/gem5/src/dev/alpha/tsunamireg.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* List of Tsunami CSRs
|
||||
*/
|
||||
|
||||
#ifndef __TSUNAMIREG_H__
|
||||
#define __TSUNAMIREG_H__
|
||||
|
||||
#define ALPHA_K0SEG_BASE ULL(0xfffffc0000000000)
|
||||
|
||||
// CChip Registers
|
||||
#define TSDEV_CC_CSR 0x00
|
||||
#define TSDEV_CC_MTR 0x01
|
||||
#define TSDEV_CC_MISC 0x02
|
||||
|
||||
#define TSDEV_CC_AAR0 0x04
|
||||
#define TSDEV_CC_AAR1 0x05
|
||||
#define TSDEV_CC_AAR2 0x06
|
||||
#define TSDEV_CC_AAR3 0x07
|
||||
#define TSDEV_CC_DIM0 0x08
|
||||
#define TSDEV_CC_DIM1 0x09
|
||||
#define TSDEV_CC_DIR0 0x0A
|
||||
#define TSDEV_CC_DIR1 0x0B
|
||||
#define TSDEV_CC_DRIR 0x0C
|
||||
#define TSDEV_CC_PRBEN 0x0D
|
||||
#define TSDEV_CC_IIC0 0x0E
|
||||
#define TSDEV_CC_IIC1 0x0F
|
||||
#define TSDEV_CC_MPR0 0x10
|
||||
#define TSDEV_CC_MPR1 0x11
|
||||
#define TSDEV_CC_MPR2 0x12
|
||||
#define TSDEV_CC_MPR3 0x13
|
||||
|
||||
#define TSDEV_CC_DIM2 0x18
|
||||
#define TSDEV_CC_DIM3 0x19
|
||||
#define TSDEV_CC_DIR2 0x1A
|
||||
#define TSDEV_CC_DIR3 0x1B
|
||||
#define TSDEV_CC_IIC2 0x1C
|
||||
#define TSDEV_CC_IIC3 0x1D
|
||||
|
||||
// BigTsunami Registers
|
||||
#define TSDEV_CC_BDIMS 0x1000000
|
||||
#define TSDEV_CC_BDIRS 0x2000000
|
||||
#define TSDEV_CC_IPIQ 0x20 //0xf01a000800
|
||||
#define TSDEV_CC_IPIR 0x21 //0xf01a000840
|
||||
#define TSDEV_CC_ITIR 0x22 //0xf01a000880
|
||||
|
||||
|
||||
// PChip Registers
|
||||
#define TSDEV_PC_WSBA0 0x00
|
||||
#define TSDEV_PC_WSBA1 0x01
|
||||
#define TSDEV_PC_WSBA2 0x02
|
||||
#define TSDEV_PC_WSBA3 0x03
|
||||
#define TSDEV_PC_WSM0 0x04
|
||||
#define TSDEV_PC_WSM1 0x05
|
||||
#define TSDEV_PC_WSM2 0x06
|
||||
#define TSDEV_PC_WSM3 0x07
|
||||
#define TSDEV_PC_TBA0 0x08
|
||||
#define TSDEV_PC_TBA1 0x09
|
||||
#define TSDEV_PC_TBA2 0x0A
|
||||
#define TSDEV_PC_TBA3 0x0B
|
||||
#define TSDEV_PC_PCTL 0x0C
|
||||
#define TSDEV_PC_PLAT 0x0D
|
||||
#define TSDEV_PC_RES 0x0E
|
||||
#define TSDEV_PC_PERROR 0x0F
|
||||
#define TSDEV_PC_PERRMASK 0x10
|
||||
#define TSDEV_PC_PERRSET 0x11
|
||||
#define TSDEV_PC_TLBIV 0x12
|
||||
#define TSDEV_PC_TLBIA 0x13
|
||||
#define TSDEV_PC_PMONCTL 0x14
|
||||
#define TSDEV_PC_PMONCNT 0x15
|
||||
|
||||
#define TSDEV_PC_SPST 0x20
|
||||
|
||||
|
||||
// DChip Registers
|
||||
#define TSDEV_DC_DSC 0x20
|
||||
#define TSDEV_DC_STR 0x21
|
||||
#define TSDEV_DC_DREV 0x22
|
||||
#define TSDEV_DC_DSC2 0x23
|
||||
|
||||
// I/O Ports
|
||||
#define TSDEV_PIC1_MASK 0x21
|
||||
#define TSDEV_PIC2_MASK 0xA1
|
||||
#define TSDEV_PIC1_ISR 0x20
|
||||
#define TSDEV_PIC2_ISR 0xA0
|
||||
#define TSDEV_PIC1_ACK 0x20
|
||||
#define TSDEV_PIC2_ACK 0xA0
|
||||
#define TSDEV_DMA1_RESET 0x0D
|
||||
#define TSDEV_DMA2_RESET 0xDA
|
||||
#define TSDEV_DMA1_MODE 0x0B
|
||||
#define TSDEV_DMA2_MODE 0xD6
|
||||
#define TSDEV_DMA1_MASK 0x0A
|
||||
#define TSDEV_DMA2_MASK 0xD4
|
||||
#define TSDEV_CTRL_PORTB 0x61
|
||||
#define TSDEV_TMR0_DATA 0x40
|
||||
#define TSDEV_TMR1_DATA 0x41
|
||||
#define TSDEV_TMR2_DATA 0x42
|
||||
#define TSDEV_TMR_CTRL 0x43
|
||||
#define TSDEV_KBD 0x64
|
||||
#define TSDEV_DMA1_CMND 0x08
|
||||
#define TSDEV_DMA1_STAT TSDEV_DMA1_CMND
|
||||
#define TSDEV_DMA2_CMND 0xD0
|
||||
#define TSDEV_DMA2_STAT TSDEV_DMA2_CMND
|
||||
#define TSDEV_DMA1_MMASK 0x0F
|
||||
#define TSDEV_DMA2_MMASK 0xDE
|
||||
|
||||
/* Added for keyboard accesses */
|
||||
#define TSDEV_KBD 0x64
|
||||
|
||||
#define TSDEV_RTC_ADDR 0x70
|
||||
#define TSDEV_RTC_DATA 0x71
|
||||
|
||||
#define PCHIP_PCI0_MEMORY ULL(0x00000000000)
|
||||
#define PCHIP_PCI0_IO ULL(0x001FC000000)
|
||||
#define TSUNAMI_UNCACHABLE_BIT ULL(0x80000000000)
|
||||
#define TSUNAMI_PCI0_MEMORY TSUNAMI_UNCACHABLE_BIT + PCHIP_PCI0_MEMORY
|
||||
#define TSUNAMI_PCI0_IO TSUNAMI_UNCACHABLE_BIT + PCHIP_PCI0_IO
|
||||
|
||||
|
||||
// System Control PortB Status Bits
|
||||
#define PORTB_SPKR_HIGH 0x20
|
||||
|
||||
#endif // __TSUNAMIREG_H__
|
||||
418
simulators/gem5/src/dev/arm/RealView.py
Normal file
418
simulators/gem5/src/dev/arm/RealView.py
Normal file
@ -0,0 +1,418 @@
|
||||
# Copyright (c) 2009-2012 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
# not be construed as granting a license to any other intellectual
|
||||
# property including but not limited to intellectual property relating
|
||||
# to a hardware implementation of the functionality of the software
|
||||
# licensed hereunder. You may use the software subject to the license
|
||||
# terms below provided that you ensure that this notice is replicated
|
||||
# unmodified and in its entirety in all distributions of the software,
|
||||
# modified or unmodified, in source code or in binary form.
|
||||
#
|
||||
# Copyright (c) 2006-2007 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
|
||||
# Gabe Black
|
||||
# William Wang
|
||||
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr, DmaDevice
|
||||
from Pci import PciConfigAll
|
||||
from Ethernet import NSGigE, IGbE_e1000, IGbE_igb
|
||||
from Ide import *
|
||||
from Platform import Platform
|
||||
from Terminal import Terminal
|
||||
from Uart import Uart
|
||||
from SimpleMemory import SimpleMemory
|
||||
|
||||
class AmbaDevice(BasicPioDevice):
|
||||
type = 'AmbaDevice'
|
||||
abstract = True
|
||||
amba_id = Param.UInt32("ID of AMBA device for kernel detection")
|
||||
|
||||
class AmbaIntDevice(AmbaDevice):
|
||||
type = 'AmbaIntDevice'
|
||||
abstract = True
|
||||
gic = Param.Gic(Parent.any, "Gic to use for interrupting")
|
||||
int_num = Param.UInt32("Interrupt number that connects to GIC")
|
||||
int_delay = Param.Latency("100ns",
|
||||
"Time between action and interrupt generation by device")
|
||||
|
||||
class AmbaDmaDevice(DmaDevice):
|
||||
type = 'AmbaDmaDevice'
|
||||
abstract = True
|
||||
pio_addr = Param.Addr("Address for AMBA slave interface")
|
||||
pio_latency = Param.Latency("10ns", "Time between action and write/read result by AMBA DMA Device")
|
||||
gic = Param.Gic(Parent.any, "Gic to use for interrupting")
|
||||
int_num = Param.UInt32("Interrupt number that connects to GIC")
|
||||
amba_id = Param.UInt32("ID of AMBA device for kernel detection")
|
||||
|
||||
class A9SCU(BasicPioDevice):
|
||||
type = 'A9SCU'
|
||||
|
||||
class RealViewCtrl(BasicPioDevice):
|
||||
type = 'RealViewCtrl'
|
||||
proc_id0 = Param.UInt32(0x0C000000, "Processor ID, SYS_PROCID")
|
||||
proc_id1 = Param.UInt32(0x0C000222, "Processor ID, SYS_PROCID1")
|
||||
idreg = Param.UInt32(0x00000000, "ID Register, SYS_ID")
|
||||
|
||||
class Gic(PioDevice):
|
||||
type = 'Gic'
|
||||
platform = Param.Platform(Parent.any, "Platform this device is part of.")
|
||||
dist_addr = Param.Addr(0x1f001000, "Address for distributor")
|
||||
cpu_addr = Param.Addr(0x1f000100, "Address for cpu")
|
||||
dist_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to distributor")
|
||||
cpu_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to cpu interface")
|
||||
int_latency = Param.Latency('10ns', "Delay for interrupt to get to CPU")
|
||||
it_lines = Param.UInt32(128, "Number of interrupt lines supported (max = 1020)")
|
||||
|
||||
class AmbaFake(AmbaDevice):
|
||||
type = 'AmbaFake'
|
||||
ignore_access = Param.Bool(False, "Ignore reads/writes to this device, (e.g. IsaFake + AMBA)")
|
||||
amba_id = 0;
|
||||
|
||||
class Pl011(Uart):
|
||||
type = 'Pl011'
|
||||
gic = Param.Gic(Parent.any, "Gic to use for interrupting")
|
||||
int_num = Param.UInt32("Interrupt number that connects to GIC")
|
||||
end_on_eot = Param.Bool(False, "End the simulation when a EOT is received on the UART")
|
||||
int_delay = Param.Latency("100ns", "Time between action and interrupt generation by UART")
|
||||
|
||||
class Sp804(AmbaDevice):
|
||||
type = 'Sp804'
|
||||
gic = Param.Gic(Parent.any, "Gic to use for interrupting")
|
||||
int_num0 = Param.UInt32("Interrupt number that connects to GIC")
|
||||
clock0 = Param.Clock('1MHz', "Clock speed of the input")
|
||||
int_num1 = Param.UInt32("Interrupt number that connects to GIC")
|
||||
clock1 = Param.Clock('1MHz', "Clock speed of the input")
|
||||
amba_id = 0x00141804
|
||||
|
||||
class CpuLocalTimer(BasicPioDevice):
|
||||
type = 'CpuLocalTimer'
|
||||
gic = Param.Gic(Parent.any, "Gic to use for interrupting")
|
||||
int_num_timer = Param.UInt32("Interrrupt number used per-cpu to GIC")
|
||||
int_num_watchdog = Param.UInt32("Interrupt number for per-cpu watchdog to GIC")
|
||||
clock = Param.Clock('1GHz', "Clock speed at which the timer counts")
|
||||
|
||||
class PL031(AmbaIntDevice):
|
||||
type = 'PL031'
|
||||
time = Param.Time('01/01/2009', "System time to use ('Now' for actual time)")
|
||||
amba_id = 0x00341031
|
||||
|
||||
class Pl050(AmbaIntDevice):
|
||||
type = 'Pl050'
|
||||
vnc = Param.VncServer(Parent.any, "Vnc server for remote frame buffer display")
|
||||
is_mouse = Param.Bool(False, "Is this interface a mouse, if not a keyboard")
|
||||
int_delay = '1us'
|
||||
amba_id = 0x00141050
|
||||
|
||||
class Pl111(AmbaDmaDevice):
|
||||
type = 'Pl111'
|
||||
clock = Param.Clock('24MHz', "Clock speed of the input")
|
||||
vnc = Param.VncServer(Parent.any, "Vnc server for remote frame buffer display")
|
||||
amba_id = 0x00141111
|
||||
|
||||
class RealView(Platform):
|
||||
type = 'RealView'
|
||||
system = Param.System(Parent.any, "system")
|
||||
pci_cfg_base = Param.Addr(0, "Base address of PCI Configuraiton Space")
|
||||
mem_start_addr = Param.Addr(0, "Start address of main memory")
|
||||
max_mem_size = Param.Addr('256MB', "Maximum amount of RAM supported by platform")
|
||||
|
||||
def setupBootLoader(self, mem_bus, cur_sys, loc):
|
||||
self.nvmem = SimpleMemory(range = AddrRange(Addr('2GB'),
|
||||
size = '64MB'),
|
||||
zero = True)
|
||||
self.nvmem.port = mem_bus.master
|
||||
cur_sys.boot_loader = loc('boot.arm')
|
||||
|
||||
|
||||
# Reference for memory map and interrupt number
|
||||
# RealView Platform Baseboard Explore for Cortex-A9 User Guide(ARM DUI 0440A)
|
||||
# Chapter 4: Programmer's Reference
|
||||
class RealViewPBX(RealView):
|
||||
uart = Pl011(pio_addr=0x10009000, int_num=44)
|
||||
realview_io = RealViewCtrl(pio_addr=0x10000000)
|
||||
gic = Gic()
|
||||
timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
|
||||
timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
|
||||
local_cpu_timer = CpuLocalTimer(int_num_timer=29, int_num_watchdog=30, pio_addr=0x1f000600)
|
||||
clcd = Pl111(pio_addr=0x10020000, int_num=55)
|
||||
kmi0 = Pl050(pio_addr=0x10006000, int_num=52)
|
||||
kmi1 = Pl050(pio_addr=0x10007000, int_num=53, is_mouse=True)
|
||||
a9scu = A9SCU(pio_addr=0x1f000000)
|
||||
cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=7, pci_bus=2,
|
||||
io_shift = 1, ctrl_offset = 2, Command = 0x1,
|
||||
BAR0 = 0x18000000, BAR0Size = '16B',
|
||||
BAR1 = 0x18000100, BAR1Size = '1B',
|
||||
BAR0LegacyIO = True, BAR1LegacyIO = True)
|
||||
|
||||
|
||||
l2x0_fake = IsaFake(pio_addr=0x1f002000, pio_size=0xfff)
|
||||
flash_fake = IsaFake(pio_addr=0x40000000, pio_size=0x20000000,
|
||||
fake_mem=True)
|
||||
dmac_fake = AmbaFake(pio_addr=0x10030000)
|
||||
uart1_fake = AmbaFake(pio_addr=0x1000a000)
|
||||
uart2_fake = AmbaFake(pio_addr=0x1000b000)
|
||||
uart3_fake = AmbaFake(pio_addr=0x1000c000)
|
||||
smc_fake = AmbaFake(pio_addr=0x100e1000)
|
||||
sp810_fake = AmbaFake(pio_addr=0x10001000, ignore_access=True)
|
||||
watchdog_fake = AmbaFake(pio_addr=0x10010000)
|
||||
gpio0_fake = AmbaFake(pio_addr=0x10013000)
|
||||
gpio1_fake = AmbaFake(pio_addr=0x10014000)
|
||||
gpio2_fake = AmbaFake(pio_addr=0x10015000)
|
||||
ssp_fake = AmbaFake(pio_addr=0x1000d000)
|
||||
sci_fake = AmbaFake(pio_addr=0x1000e000)
|
||||
aaci_fake = AmbaFake(pio_addr=0x10004000)
|
||||
mmc_fake = AmbaFake(pio_addr=0x10005000)
|
||||
rtc = PL031(pio_addr=0x10017000, int_num=42)
|
||||
|
||||
|
||||
# Attach I/O devices that are on chip and also set the appropriate
|
||||
# ranges for the bridge
|
||||
def attachOnChipIO(self, bus, bridge):
|
||||
self.gic.pio = bus.master
|
||||
self.l2x0_fake.pio = bus.master
|
||||
self.a9scu.pio = bus.master
|
||||
self.local_cpu_timer.pio = bus.master
|
||||
# Bridge ranges based on excluding what is part of on-chip I/O
|
||||
# (gic, l2x0, a9scu, local_cpu_timer)
|
||||
bridge.ranges = [AddrRange(self.realview_io.pio_addr,
|
||||
self.a9scu.pio_addr - 1),
|
||||
AddrRange(self.flash_fake.pio_addr,
|
||||
self.flash_fake.pio_addr + \
|
||||
self.flash_fake.pio_size - 1)]
|
||||
|
||||
# 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.
|
||||
def attachIO(self, bus):
|
||||
self.uart.pio = bus.master
|
||||
self.realview_io.pio = bus.master
|
||||
self.timer0.pio = bus.master
|
||||
self.timer1.pio = bus.master
|
||||
self.clcd.pio = bus.master
|
||||
self.clcd.dma = bus.slave
|
||||
self.kmi0.pio = bus.master
|
||||
self.kmi1.pio = bus.master
|
||||
self.cf_ctrl.pio = bus.master
|
||||
self.cf_ctrl.config = bus.master
|
||||
self.cf_ctrl.dma = bus.slave
|
||||
self.dmac_fake.pio = bus.master
|
||||
self.uart1_fake.pio = bus.master
|
||||
self.uart2_fake.pio = bus.master
|
||||
self.uart3_fake.pio = bus.master
|
||||
self.smc_fake.pio = bus.master
|
||||
self.sp810_fake.pio = bus.master
|
||||
self.watchdog_fake.pio = bus.master
|
||||
self.gpio0_fake.pio = bus.master
|
||||
self.gpio1_fake.pio = bus.master
|
||||
self.gpio2_fake.pio = bus.master
|
||||
self.ssp_fake.pio = bus.master
|
||||
self.sci_fake.pio = bus.master
|
||||
self.aaci_fake.pio = bus.master
|
||||
self.mmc_fake.pio = bus.master
|
||||
self.rtc.pio = bus.master
|
||||
self.flash_fake.pio = bus.master
|
||||
|
||||
# Reference for memory map and interrupt number
|
||||
# RealView Emulation Baseboard User Guide (ARM DUI 0143B)
|
||||
# Chapter 4: Programmer's Reference
|
||||
class RealViewEB(RealView):
|
||||
uart = Pl011(pio_addr=0x10009000, int_num=44)
|
||||
realview_io = RealViewCtrl(pio_addr=0x10000000)
|
||||
gic = Gic(dist_addr=0x10041000, cpu_addr=0x10040000)
|
||||
timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
|
||||
timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
|
||||
clcd = Pl111(pio_addr=0x10020000, int_num=23)
|
||||
kmi0 = Pl050(pio_addr=0x10006000, int_num=20)
|
||||
kmi1 = Pl050(pio_addr=0x10007000, int_num=21, is_mouse=True)
|
||||
|
||||
l2x0_fake = IsaFake(pio_addr=0x1f002000, pio_size=0xfff, warn_access="1")
|
||||
flash_fake = IsaFake(pio_addr=0x40000000, pio_size=0x20000000-1,
|
||||
fake_mem=True)
|
||||
dmac_fake = AmbaFake(pio_addr=0x10030000)
|
||||
uart1_fake = AmbaFake(pio_addr=0x1000a000)
|
||||
uart2_fake = AmbaFake(pio_addr=0x1000b000)
|
||||
uart3_fake = AmbaFake(pio_addr=0x1000c000)
|
||||
smcreg_fake = IsaFake(pio_addr=0x10080000, pio_size=0x10000-1)
|
||||
smc_fake = AmbaFake(pio_addr=0x100e1000)
|
||||
sp810_fake = AmbaFake(pio_addr=0x10001000, ignore_access=True)
|
||||
watchdog_fake = AmbaFake(pio_addr=0x10010000)
|
||||
gpio0_fake = AmbaFake(pio_addr=0x10013000)
|
||||
gpio1_fake = AmbaFake(pio_addr=0x10014000)
|
||||
gpio2_fake = AmbaFake(pio_addr=0x10015000)
|
||||
ssp_fake = AmbaFake(pio_addr=0x1000d000)
|
||||
sci_fake = AmbaFake(pio_addr=0x1000e000)
|
||||
aaci_fake = AmbaFake(pio_addr=0x10004000)
|
||||
mmc_fake = AmbaFake(pio_addr=0x10005000)
|
||||
rtc_fake = AmbaFake(pio_addr=0x10017000, amba_id=0x41031)
|
||||
|
||||
|
||||
|
||||
# Attach I/O devices that are on chip and also set the appropriate
|
||||
# ranges for the bridge
|
||||
def attachOnChipIO(self, bus, bridge):
|
||||
self.gic.pio = bus.master
|
||||
self.l2x0_fake.pio = bus.master
|
||||
# Bridge ranges based on excluding what is part of on-chip I/O
|
||||
# (gic, l2x0)
|
||||
bridge.ranges = [AddrRange(self.realview_io.pio_addr,
|
||||
self.gic.cpu_addr - 1),
|
||||
AddrRange(self.flash_fake.pio_addr, Addr.max)]
|
||||
|
||||
# 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.
|
||||
def attachIO(self, bus):
|
||||
self.uart.pio = bus.master
|
||||
self.realview_io.pio = bus.master
|
||||
self.timer0.pio = bus.master
|
||||
self.timer1.pio = bus.master
|
||||
self.clcd.pio = bus.master
|
||||
self.clcd.dma = bus.slave
|
||||
self.kmi0.pio = bus.master
|
||||
self.kmi1.pio = bus.master
|
||||
self.dmac_fake.pio = bus.master
|
||||
self.uart1_fake.pio = bus.master
|
||||
self.uart2_fake.pio = bus.master
|
||||
self.uart3_fake.pio = bus.master
|
||||
self.smc_fake.pio = bus.master
|
||||
self.sp810_fake.pio = bus.master
|
||||
self.watchdog_fake.pio = bus.master
|
||||
self.gpio0_fake.pio = bus.master
|
||||
self.gpio1_fake.pio = bus.master
|
||||
self.gpio2_fake.pio = bus.master
|
||||
self.ssp_fake.pio = bus.master
|
||||
self.sci_fake.pio = bus.master
|
||||
self.aaci_fake.pio = bus.master
|
||||
self.mmc_fake.pio = bus.master
|
||||
self.rtc_fake.pio = bus.master
|
||||
self.flash_fake.pio = bus.master
|
||||
self.smcreg_fake.pio = bus.master
|
||||
|
||||
class VExpress_EMM(RealView):
|
||||
mem_start_addr = '2GB'
|
||||
max_mem_size = '2GB'
|
||||
pci_cfg_base = 0x30000000
|
||||
uart = Pl011(pio_addr=0x1c090000, int_num=37)
|
||||
realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000, pio_addr=0x1C010000)
|
||||
gic = Gic(dist_addr=0x2C001000, cpu_addr=0x2C002000)
|
||||
local_cpu_timer = CpuLocalTimer(int_num_timer=29, int_num_watchdog=30, pio_addr=0x2C080000)
|
||||
timer0 = Sp804(int_num0=34, int_num1=34, pio_addr=0x1C110000, clock0='50MHz', clock1='50MHz')
|
||||
timer1 = Sp804(int_num0=35, int_num1=35, pio_addr=0x1C120000, clock0='50MHz', clock1='50MHz')
|
||||
clcd = Pl111(pio_addr=0x1c1f0000, int_num=46)
|
||||
kmi0 = Pl050(pio_addr=0x1c060000, int_num=44)
|
||||
kmi1 = Pl050(pio_addr=0x1c070000, int_num=45)
|
||||
cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=0, pci_bus=2,
|
||||
io_shift = 2, ctrl_offset = 2, Command = 0x1,
|
||||
BAR0 = 0x1C1A0000, BAR0Size = '256B',
|
||||
BAR1 = 0x1C1A0100, BAR1Size = '4096B',
|
||||
BAR0LegacyIO = True, BAR1LegacyIO = True)
|
||||
|
||||
pciconfig = PciConfigAll(size='256MB')
|
||||
ethernet = IGbE_e1000(pci_bus=0, pci_dev=0, pci_func=0,
|
||||
InterruptLine=1, InterruptPin=1)
|
||||
|
||||
ide = IdeController(disks = [], pci_bus=0, pci_dev=1, pci_func=0,
|
||||
InterruptLine=2, InterruptPin=2)
|
||||
|
||||
|
||||
vram = SimpleMemory(range = AddrRange(0x18000000, size='32MB'),
|
||||
zero = True)
|
||||
rtc = PL031(pio_addr=0x1C170000, int_num=36)
|
||||
|
||||
l2x0_fake = IsaFake(pio_addr=0x2C100000, pio_size=0xfff)
|
||||
uart1_fake = AmbaFake(pio_addr=0x1C0A0000)
|
||||
uart2_fake = AmbaFake(pio_addr=0x1C0B0000)
|
||||
uart3_fake = AmbaFake(pio_addr=0x1C0C0000)
|
||||
sp810_fake = AmbaFake(pio_addr=0x1C020000, ignore_access=True)
|
||||
watchdog_fake = AmbaFake(pio_addr=0x1C0F0000)
|
||||
aaci_fake = AmbaFake(pio_addr=0x1C040000)
|
||||
lan_fake = IsaFake(pio_addr=0x1A000000, pio_size=0xffff)
|
||||
usb_fake = IsaFake(pio_addr=0x1B000000, pio_size=0x1ffff)
|
||||
mmc_fake = AmbaFake(pio_addr=0x1c050000)
|
||||
|
||||
def setupBootLoader(self, mem_bus, cur_sys, loc):
|
||||
self.nvmem = SimpleMemory(range = AddrRange(0, size = '64MB'),
|
||||
zero = True)
|
||||
self.nvmem.port = mem_bus.master
|
||||
cur_sys.boot_loader = loc('boot_emm.arm')
|
||||
cur_sys.atags_addr = 0x80000100
|
||||
|
||||
# Attach I/O devices that are on chip and also set the appropriate
|
||||
# ranges for the bridge
|
||||
def attachOnChipIO(self, bus, bridge):
|
||||
self.gic.pio = bus.master
|
||||
self.local_cpu_timer.pio = bus.master
|
||||
# Bridge ranges based on excluding what is part of on-chip I/O
|
||||
# (gic, a9scu)
|
||||
bridge.ranges = [AddrRange(0x2F000000, size='16MB'),
|
||||
AddrRange(0x30000000, size='256MB'),
|
||||
AddrRange(0x40000000, size='512MB'),
|
||||
AddrRange(0x18000000, size='64MB'),
|
||||
AddrRange(0x1C000000, size='64MB')]
|
||||
|
||||
# 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.
|
||||
def attachIO(self, bus):
|
||||
self.uart.pio = bus.master
|
||||
self.realview_io.pio = bus.master
|
||||
self.timer0.pio = bus.master
|
||||
self.timer1.pio = bus.master
|
||||
self.clcd.pio = bus.master
|
||||
self.clcd.dma = bus.slave
|
||||
self.kmi0.pio = bus.master
|
||||
self.kmi1.pio = bus.master
|
||||
self.cf_ctrl.pio = bus.master
|
||||
self.cf_ctrl.dma = bus.slave
|
||||
self.cf_ctrl.config = bus.master
|
||||
self.rtc.pio = bus.master
|
||||
bus.use_default_range = True
|
||||
self.vram.port = bus.master
|
||||
self.ide.pio = bus.master
|
||||
self.ide.config = bus.master
|
||||
self.ide.dma = bus.slave
|
||||
self.ethernet.pio = bus.master
|
||||
self.ethernet.config = bus.master
|
||||
self.ethernet.dma = bus.slave
|
||||
self.pciconfig.pio = bus.default
|
||||
|
||||
self.l2x0_fake.pio = bus.master
|
||||
self.uart1_fake.pio = bus.master
|
||||
self.uart2_fake.pio = bus.master
|
||||
self.uart3_fake.pio = bus.master
|
||||
self.sp810_fake.pio = bus.master
|
||||
self.watchdog_fake.pio = bus.master
|
||||
self.aaci_fake.pio = bus.master
|
||||
self.lan_fake.pio = bus.master
|
||||
self.usb_fake.pio = bus.master
|
||||
self.mmc_fake.pio = bus.master
|
||||
|
||||
61
simulators/gem5/src/dev/arm/SConscript
Normal file
61
simulators/gem5/src/dev/arm/SConscript
Normal file
@ -0,0 +1,61 @@
|
||||
# -*- mode:python -*-
|
||||
|
||||
# Copyright (c) 2009 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
# not be construed as granting a license to any other intellectual
|
||||
# property including but not limited to intellectual property relating
|
||||
# to a hardware implementation of the functionality of the software
|
||||
# licensed hereunder. You may use the software subject to the license
|
||||
# terms below provided that you ensure that this notice is replicated
|
||||
# unmodified and in its entirety in all distributions of the software,
|
||||
# modified or unmodified, in source code or in binary form.
|
||||
#
|
||||
# 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
|
||||
|
||||
Import('*')
|
||||
|
||||
if env['TARGET_ISA'] == 'arm':
|
||||
SimObject('RealView.py')
|
||||
|
||||
Source('a9scu.cc')
|
||||
Source('amba_device.cc')
|
||||
Source('amba_fake.cc')
|
||||
Source('gic.cc')
|
||||
Source('pl011.cc')
|
||||
Source('pl111.cc')
|
||||
Source('kmi.cc')
|
||||
Source('timer_sp804.cc')
|
||||
Source('rv_ctrl.cc')
|
||||
Source('realview.cc')
|
||||
Source('rtc_pl031.cc')
|
||||
Source('timer_cpulocal.cc')
|
||||
|
||||
DebugFlag('AMBA')
|
||||
DebugFlag('PL111')
|
||||
DebugFlag('Pl050')
|
||||
DebugFlag('GIC')
|
||||
102
simulators/gem5/src/dev/arm/a9scu.cc
Normal file
102
simulators/gem5/src/dev/arm/a9scu.cc
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "base/intmath.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "dev/arm/a9scu.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
A9SCU::A9SCU(Params *p)
|
||||
: BasicPioDevice(p)
|
||||
{
|
||||
pioSize = 0x60;
|
||||
}
|
||||
|
||||
Tick
|
||||
A9SCU::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == 4);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
|
||||
switch(daddr) {
|
||||
case Control:
|
||||
pkt->set(1); // SCU already enabled
|
||||
break;
|
||||
case Config:
|
||||
assert(sys->numContexts() <= 4);
|
||||
int smp_bits, core_cnt;
|
||||
smp_bits = power(2,sys->numContexts()) - 1;
|
||||
core_cnt = sys->numContexts() - 1;
|
||||
pkt->set(smp_bits << 4 | core_cnt);
|
||||
break;
|
||||
default:
|
||||
// Only configuration register is implemented
|
||||
panic("Tried to read SCU at offset %#x\n", daddr);
|
||||
break;
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
|
||||
}
|
||||
|
||||
Tick
|
||||
A9SCU::write(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
switch (daddr) {
|
||||
default:
|
||||
// Nothing implemented at this point
|
||||
panic("Tried to write SCU at offset %#x\n", daddr);
|
||||
break;
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
A9SCU *
|
||||
A9SCUParams::create()
|
||||
{
|
||||
return new A9SCU(this);
|
||||
}
|
||||
85
simulators/gem5/src/dev/arm/a9scu.hh
Normal file
85
simulators/gem5/src/dev/arm/a9scu.hh
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_A9SCU_HH__
|
||||
#define __DEV_ARM_A9SCU_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "params/A9SCU.hh"
|
||||
|
||||
/** @file
|
||||
* This defines the snoop control unit register on an A9
|
||||
*/
|
||||
|
||||
class A9SCU : public BasicPioDevice
|
||||
{
|
||||
protected:
|
||||
enum {
|
||||
Control = 0x00,
|
||||
Config = 0x04,
|
||||
};
|
||||
|
||||
public:
|
||||
typedef A9SCUParams Params;
|
||||
|
||||
/**
|
||||
* The constructor for RealView just registers itself with the MMU.
|
||||
* @param p params structure
|
||||
*/
|
||||
A9SCU(Params *p);
|
||||
|
||||
/**
|
||||
* Handle a read to the device
|
||||
* @param pkt The memory request.
|
||||
* @param data Where to put the data.
|
||||
*/
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* All writes are panic.
|
||||
* @param pkt The memory request.
|
||||
* @param data the data
|
||||
*/
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
};
|
||||
|
||||
|
||||
#endif // __DEV_ARM_A9SCU_HH__
|
||||
|
||||
90
simulators/gem5/src/dev/arm/amba_device.cc
Normal file
90
simulators/gem5/src/dev/arm/amba_device.cc
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 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
|
||||
*/
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "debug/AMBA.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "dev/arm/amba_fake.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
const uint64_t AmbaVendor = ULL(0xb105f00d00000000);
|
||||
|
||||
AmbaDevice::AmbaDevice(const Params *p)
|
||||
: BasicPioDevice(p), ambaId(AmbaVendor | p->amba_id)
|
||||
{
|
||||
}
|
||||
|
||||
AmbaIntDevice::AmbaIntDevice(const Params *p)
|
||||
: AmbaDevice(p), intNum(p->int_num), gic(p->gic), intDelay(p->int_delay)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
AmbaDmaDevice::AmbaDmaDevice(const Params *p)
|
||||
: DmaDevice(p), ambaId(AmbaVendor | p->amba_id),
|
||||
pioAddr(p->pio_addr), pioSize(0),
|
||||
pioDelay(p->pio_latency),intNum(p->int_num), gic(p->gic)
|
||||
{
|
||||
}
|
||||
|
||||
namespace AmbaDev {
|
||||
bool
|
||||
readId(PacketPtr pkt, uint64_t amba_id, Addr pio_addr)
|
||||
{
|
||||
Addr daddr = pkt->getAddr() - pio_addr;
|
||||
if (daddr < AMBA_PER_ID0 || daddr > AMBA_CEL_ID3)
|
||||
return false;
|
||||
|
||||
pkt->allocate();
|
||||
|
||||
int byte = (daddr - AMBA_PER_ID0) << 1;
|
||||
// Too noisy right now
|
||||
DPRINTF(AMBA, "Returning %#x for offset %#x(%d)\n", (amba_id >> byte) & 0xFF,
|
||||
pkt->getAddr() - pio_addr, byte);
|
||||
assert(pkt->getSize() == 4);
|
||||
pkt->set<uint32_t>((amba_id >> byte) & 0xFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace AmbaDev
|
||||
114
simulators/gem5/src/dev/arm/amba_device.hh
Normal file
114
simulators/gem5/src/dev/arm/amba_device.hh
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 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 is a base class for AMBA devices that have to respond to Device and
|
||||
* Implementer ID calls.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_AMBA_DEVICE_HH__
|
||||
#define __DEV_ARM_AMBA_DEVICE_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/arm/gic.hh"
|
||||
#include "dev/dma_device.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "params/AmbaDevice.hh"
|
||||
#include "params/AmbaDmaDevice.hh"
|
||||
#include "params/AmbaIntDevice.hh"
|
||||
|
||||
namespace AmbaDev {
|
||||
|
||||
const int AMBA_PER_ID0 = 0xFE0;
|
||||
const int AMBA_PER_ID1 = 0xFE4;
|
||||
const int AMBA_PER_ID2 = 0xFE8;
|
||||
const int AMBA_PER_ID3 = 0xFEC;
|
||||
const int AMBA_CEL_ID0 = 0xFF0;
|
||||
const int AMBA_CEL_ID1 = 0xFF4;
|
||||
const int AMBA_CEL_ID2 = 0xFF8;
|
||||
const int AMBA_CEL_ID3 = 0xFFC;
|
||||
|
||||
bool readId(PacketPtr pkt, uint64_t amba_id, Addr pio_addr);
|
||||
}
|
||||
|
||||
class AmbaDevice : public BasicPioDevice
|
||||
{
|
||||
protected:
|
||||
uint64_t ambaId;
|
||||
|
||||
public:
|
||||
typedef AmbaDeviceParams Params;
|
||||
AmbaDevice(const Params *p);
|
||||
};
|
||||
|
||||
class AmbaIntDevice : public AmbaDevice
|
||||
{
|
||||
protected:
|
||||
int intNum;
|
||||
Gic *gic;
|
||||
Tick intDelay;
|
||||
|
||||
public:
|
||||
typedef AmbaIntDeviceParams Params;
|
||||
AmbaIntDevice(const Params *p);
|
||||
};
|
||||
|
||||
class AmbaDmaDevice : public DmaDevice
|
||||
{
|
||||
protected:
|
||||
uint64_t ambaId;
|
||||
Addr pioAddr;
|
||||
Addr pioSize;
|
||||
Tick pioDelay;
|
||||
int intNum;
|
||||
Gic *gic;
|
||||
|
||||
public:
|
||||
typedef AmbaDmaDeviceParams Params;
|
||||
AmbaDmaDevice(const Params *p);
|
||||
};
|
||||
|
||||
|
||||
#endif //__DEV_ARM_AMBA_DEVICE_HH__
|
||||
94
simulators/gem5/src/dev/arm/amba_fake.cc
Normal file
94
simulators/gem5/src/dev/arm/amba_fake.cc
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 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
|
||||
*/
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "debug/AMBA.hh"
|
||||
#include "dev/arm/amba_fake.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
using namespace AmbaDev;
|
||||
|
||||
AmbaFake::AmbaFake(const Params *p)
|
||||
: AmbaDevice(p)
|
||||
{
|
||||
pioSize = 0xfff;
|
||||
}
|
||||
|
||||
Tick
|
||||
AmbaFake::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
|
||||
DPRINTF(AMBA, " read register %#x\n", daddr);
|
||||
|
||||
pkt->set<uint32_t>(0);
|
||||
if (!readId(pkt, ambaId, pioAddr) && !params()->ignore_access)
|
||||
panic("Tried to read AmbaFake at offset %#x that doesn't exist\n", daddr);
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
AmbaFake::write(PacketPtr pkt)
|
||||
{
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
|
||||
if (!params()->ignore_access)
|
||||
panic("Tried to write AmbaFake at offset %#x that doesn't exist\n", daddr);
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
|
||||
AmbaFake *
|
||||
AmbaFakeParams::create()
|
||||
{
|
||||
return new AmbaFake(this);
|
||||
}
|
||||
74
simulators/gem5/src/dev/arm/amba_fake.hh
Normal file
74
simulators/gem5/src/dev/arm/amba_fake.hh
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 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 sits in memory and reponds appropriately so the linux kernel
|
||||
* ignores the device it is trying to talk to. It is used so the kernel doesn't
|
||||
* need to be modified and devices that we are not interested in will simply be
|
||||
* skipped.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_AMBA_FAKE_H__
|
||||
#define __DEV_ARM_AMBA_FAKE_H__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "params/AmbaFake.hh"
|
||||
|
||||
class AmbaFake : public AmbaDevice
|
||||
{
|
||||
public:
|
||||
typedef AmbaFakeParams Params;
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
AmbaFake(const Params *p);
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
};
|
||||
|
||||
#endif //__DEV_ARM_AMBA_FAKE_H__
|
||||
843
simulators/gem5/src/dev/arm/gic.cc
Normal file
843
simulators/gem5/src/dev/arm/gic.cc
Normal file
@ -0,0 +1,843 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 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
|
||||
* Prakash Ramrakhyani
|
||||
*/
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "debug/Checkpoint.hh"
|
||||
#include "debug/GIC.hh"
|
||||
#include "debug/IPI.hh"
|
||||
#include "debug/Interrupt.hh"
|
||||
#include "dev/arm/gic.hh"
|
||||
#include "dev/arm/realview.hh"
|
||||
#include "dev/terminal.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
Gic::Gic(const Params *p)
|
||||
: PioDevice(p), platform(p->platform), distAddr(p->dist_addr),
|
||||
cpuAddr(p->cpu_addr), distPioDelay(p->dist_pio_delay),
|
||||
cpuPioDelay(p->cpu_pio_delay), intLatency(p->int_latency),
|
||||
enabled(false), itLines(p->it_lines)
|
||||
{
|
||||
itLinesLog2 = ceilLog2(itLines);
|
||||
|
||||
for (int x = 0; x < CPU_MAX; x++) {
|
||||
cpuEnabled[x] = false;
|
||||
cpuPriority[x] = 0xff;
|
||||
cpuBpr[x] = 0;
|
||||
// Initialize cpu highest int
|
||||
cpuHighestInt[x] = SPURIOUS_INT;
|
||||
postIntEvent[x] = new PostIntEvent(x, p->platform);
|
||||
}
|
||||
DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled[0],
|
||||
cpuEnabled[1]);
|
||||
|
||||
for (int x = 0; x < INT_BITS_MAX; x++) {
|
||||
intEnabled[x] = 0;
|
||||
pendingInt[x] = 0;
|
||||
activeInt[x] = 0;
|
||||
}
|
||||
|
||||
for (int x = 0; x < INT_LINES_MAX; x++) {
|
||||
intPriority[x] = 0;
|
||||
cpuTarget[x] = 0;
|
||||
}
|
||||
|
||||
for (int x = 0; x < INT_BITS_MAX*2; x++) {
|
||||
intConfig[x] = 0;
|
||||
}
|
||||
|
||||
for (int x = 0; x < SGI_MAX; x++) {
|
||||
cpuSgiActive[x] = 0;
|
||||
cpuSgiPending[x] = 0;
|
||||
}
|
||||
for (int x = 0; x < CPU_MAX; x++) {
|
||||
cpuPpiActive[x] = 0;
|
||||
cpuPpiPending[x] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < CPU_MAX; i++) {
|
||||
for (int j = 0; j < (SGI_MAX + PPI_MAX); j++) {
|
||||
bankedIntPriority[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
RealView *rv = dynamic_cast<RealView*>(p->platform);
|
||||
assert(rv);
|
||||
rv->setGic(this);
|
||||
|
||||
}
|
||||
|
||||
Tick
|
||||
Gic::read(PacketPtr pkt)
|
||||
{
|
||||
|
||||
Addr addr = pkt->getAddr();
|
||||
|
||||
if (addr >= distAddr && addr < distAddr + DIST_SIZE)
|
||||
return readDistributor(pkt);
|
||||
else if (addr >= cpuAddr && addr < cpuAddr + CPU_SIZE)
|
||||
return readCpu(pkt);
|
||||
else
|
||||
panic("Read to unknown address %#x\n", pkt->getAddr());
|
||||
}
|
||||
|
||||
|
||||
Tick
|
||||
Gic::write(PacketPtr pkt)
|
||||
{
|
||||
|
||||
Addr addr = pkt->getAddr();
|
||||
|
||||
if (addr >= distAddr && addr < distAddr + DIST_SIZE)
|
||||
return writeDistributor(pkt);
|
||||
else if (addr >= cpuAddr && addr < cpuAddr + CPU_SIZE)
|
||||
return writeCpu(pkt);
|
||||
else
|
||||
panic("Write to unknown address %#x\n", pkt->getAddr());
|
||||
}
|
||||
|
||||
Tick
|
||||
Gic::readDistributor(PacketPtr pkt)
|
||||
{
|
||||
Addr daddr = pkt->getAddr() - distAddr;
|
||||
pkt->allocate();
|
||||
|
||||
int ctx_id = pkt->req->contextId();
|
||||
|
||||
DPRINTF(GIC, "gic distributor read register %#x\n", daddr);
|
||||
|
||||
if (daddr >= ICDISER_ST && daddr < ICDISER_ED + 4) {
|
||||
assert((daddr-ICDISER_ST) >> 2 < 32);
|
||||
pkt->set<uint32_t>(intEnabled[(daddr-ICDISER_ST)>>2]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDICER_ST && daddr < ICDICER_ED + 4) {
|
||||
assert((daddr-ICDICER_ST) >> 2 < 32);
|
||||
pkt->set<uint32_t>(intEnabled[(daddr-ICDICER_ST)>>2]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDISPR_ST && daddr < ICDISPR_ED + 4) {
|
||||
assert((daddr-ICDISPR_ST) >> 2 < 32);
|
||||
pkt->set<uint32_t>(pendingInt[(daddr-ICDISPR_ST)>>2]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDICPR_ST && daddr < ICDICPR_ED + 4) {
|
||||
assert((daddr-ICDICPR_ST) >> 2 < 32);
|
||||
pkt->set<uint32_t>(pendingInt[(daddr-ICDICPR_ST)>>2]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDABR_ST && daddr < ICDABR_ED + 4) {
|
||||
assert((daddr-ICDABR_ST) >> 2 < 32);
|
||||
pkt->set<uint32_t>(activeInt[(daddr-ICDABR_ST)>>2]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDIPR_ST && daddr < ICDIPR_ED + 4) {
|
||||
Addr int_num;
|
||||
int_num = daddr - ICDIPR_ST;
|
||||
assert(int_num < INT_LINES_MAX);
|
||||
DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n",int_num);
|
||||
|
||||
uint8_t* int_p;
|
||||
if (int_num < (SGI_MAX + PPI_MAX))
|
||||
int_p = bankedIntPriority[ctx_id];
|
||||
else
|
||||
int_p = intPriority;
|
||||
|
||||
switch (pkt->getSize()) {
|
||||
case 1:
|
||||
pkt->set<uint8_t>(int_p[int_num]);
|
||||
break;
|
||||
case 2:
|
||||
assert((int_num + 1) < INT_LINES_MAX);
|
||||
pkt->set<uint16_t>(int_p[int_num] |
|
||||
int_p[int_num+1] << 8);
|
||||
break;
|
||||
case 4:
|
||||
assert((int_num + 3) < INT_LINES_MAX);
|
||||
pkt->set<uint32_t>(int_p[int_num] |
|
||||
int_p[int_num+1] << 8 |
|
||||
int_p[int_num+2] << 16 |
|
||||
int_p[int_num+3] << 24);
|
||||
break;
|
||||
default:
|
||||
panic("Invalid size while reading priority regs in GIC: %d\n",
|
||||
pkt->getSize());
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDIPTR_ST && daddr < ICDIPTR_ED + 4) {
|
||||
Addr int_num;
|
||||
int_num = (daddr-ICDIPTR_ST) ;
|
||||
DPRINTF(GIC, "Reading processor target register for int# %#x \n",
|
||||
int_num);
|
||||
assert(int_num < INT_LINES_MAX);
|
||||
|
||||
// First 31 interrupts only target single processor (SGI)
|
||||
if (int_num > 31) {
|
||||
if (pkt->getSize() == 1) {
|
||||
pkt->set<uint8_t>(cpuTarget[int_num]);
|
||||
} else {
|
||||
assert(pkt->getSize() == 4);
|
||||
int_num = mbits(int_num, 31, 2);
|
||||
pkt->set<uint32_t>(cpuTarget[int_num] |
|
||||
cpuTarget[int_num+1] << 8 |
|
||||
cpuTarget[int_num+2] << 16 |
|
||||
cpuTarget[int_num+3] << 24) ;
|
||||
}
|
||||
} else {
|
||||
int ctx_id = pkt->req->contextId();
|
||||
assert(ctx_id < sys->numRunningContexts());
|
||||
pkt->set<uint32_t>(ctx_id);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDICFR_ST && daddr < ICDICFR_ED + 4) {
|
||||
assert((daddr-ICDICFR_ST) >> 2 < 64);
|
||||
/** @todo software generated interrutps and PPIs
|
||||
* can't be configured in some ways
|
||||
*/
|
||||
pkt->set<uint32_t>(intConfig[(daddr-ICDICFR_ST)>>2]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch(daddr) {
|
||||
case ICDDCR:
|
||||
pkt->set<uint32_t>(enabled);
|
||||
break;
|
||||
case ICDICTR:
|
||||
uint32_t tmp;
|
||||
tmp = ((sys->numRunningContexts() - 1) << 5) |
|
||||
(itLines/INT_BITS_MAX -1);
|
||||
pkt->set<uint32_t>(tmp);
|
||||
break;
|
||||
default:
|
||||
panic("Tried to read Gic distributor at offset %#x\n", daddr);
|
||||
break;
|
||||
}
|
||||
done:
|
||||
pkt->makeAtomicResponse();
|
||||
return distPioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
Gic::readCpu(PacketPtr pkt)
|
||||
{
|
||||
Addr daddr = pkt->getAddr() - cpuAddr;
|
||||
pkt->allocate();
|
||||
|
||||
assert(pkt->req->hasContextId());
|
||||
int ctx_id = pkt->req->contextId();
|
||||
assert(ctx_id < sys->numRunningContexts());
|
||||
|
||||
DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr,
|
||||
ctx_id);
|
||||
|
||||
switch(daddr) {
|
||||
case ICCICR:
|
||||
pkt->set<uint32_t>(cpuEnabled[ctx_id]);
|
||||
break;
|
||||
case ICCPMR:
|
||||
pkt->set<uint32_t>(cpuPriority[ctx_id]);
|
||||
break;
|
||||
case ICCBPR:
|
||||
pkt->set<uint32_t>(cpuBpr[ctx_id]);
|
||||
break;
|
||||
case ICCIAR:
|
||||
if (enabled && cpuEnabled[ctx_id]) {
|
||||
int active_int = cpuHighestInt[ctx_id];
|
||||
IAR iar = 0;
|
||||
iar.ack_id = active_int;
|
||||
iar.cpu_id = 0;
|
||||
if (active_int < SGI_MAX) {
|
||||
// this is a software interrupt from another CPU
|
||||
if (!cpuSgiPending[active_int])
|
||||
panic("Interrupt %d active but no CPU generated it?\n",
|
||||
active_int);
|
||||
for (int x = 0; x < CPU_MAX; x++) {
|
||||
// See which CPU generated the interrupt
|
||||
uint8_t cpugen =
|
||||
bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x);
|
||||
if (cpugen & (1 << ctx_id)) {
|
||||
iar.cpu_id = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint64_t sgi_num = ULL(1) << (ctx_id + 8 * iar.cpu_id);
|
||||
cpuSgiActive[iar.ack_id] |= sgi_num;
|
||||
cpuSgiPending[iar.ack_id] &= ~sgi_num;
|
||||
} else if (active_int < (SGI_MAX + PPI_MAX) ) {
|
||||
uint32_t int_num = 1 << (cpuHighestInt[ctx_id] - SGI_MAX);
|
||||
cpuPpiActive[ctx_id] |= int_num;
|
||||
updateRunPri();
|
||||
cpuPpiPending[ctx_id] &= ~int_num;
|
||||
|
||||
} else {
|
||||
uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx_id]);
|
||||
activeInt[intNumToWord(cpuHighestInt[ctx_id])] |= int_num;
|
||||
updateRunPri();
|
||||
pendingInt[intNumToWord(cpuHighestInt[ctx_id])] &= ~int_num;
|
||||
}
|
||||
|
||||
DPRINTF(Interrupt,"CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
|
||||
ctx_id, iar.ack_id, iar.cpu_id, iar);
|
||||
cpuHighestInt[ctx_id] = SPURIOUS_INT;
|
||||
updateIntState(-1);
|
||||
pkt->set<uint32_t>(iar);
|
||||
platform->intrctrl->clear(ctx_id, ArmISA::INT_IRQ, 0);
|
||||
} else {
|
||||
pkt->set<uint32_t>(SPURIOUS_INT);
|
||||
}
|
||||
|
||||
break;
|
||||
case ICCRPR:
|
||||
pkt->set<uint32_t>(iccrpr[0]);
|
||||
break;
|
||||
case ICCHPIR:
|
||||
pkt->set<uint32_t>(0);
|
||||
panic("Need to implement HPIR");
|
||||
break;
|
||||
default:
|
||||
panic("Tried to read Gic cpu at offset %#x\n", daddr);
|
||||
break;
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return cpuPioDelay;
|
||||
}
|
||||
|
||||
|
||||
Tick
|
||||
Gic::writeDistributor(PacketPtr pkt)
|
||||
{
|
||||
Addr daddr = pkt->getAddr() - distAddr;
|
||||
pkt->allocate();
|
||||
|
||||
assert(pkt->req->hasContextId());
|
||||
int ctx_id = pkt->req->contextId();
|
||||
|
||||
DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n",
|
||||
daddr, pkt->getSize(), pkt->get<uint32_t>());
|
||||
|
||||
if (daddr >= ICDISER_ST && daddr < ICDISER_ED + 4) {
|
||||
assert((daddr-ICDISER_ST) >> 2 < 32);
|
||||
intEnabled[(daddr-ICDISER_ST) >> 2] |= pkt->get<uint32_t>();
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDICER_ST && daddr < ICDICER_ED + 4) {
|
||||
assert((daddr-ICDICER_ST) >> 2 < 32);
|
||||
intEnabled[(daddr-ICDICER_ST) >> 2] &= ~pkt->get<uint32_t>();
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDISPR_ST && daddr < ICDISPR_ED + 4) {
|
||||
assert((daddr-ICDISPR_ST) >> 2 < 32);
|
||||
pendingInt[(daddr-ICDISPR_ST) >> 2] |= pkt->get<uint32_t>();
|
||||
pendingInt[0] &= SGI_MASK; // Don't allow SGIs to be changed
|
||||
updateIntState((daddr-ICDISPR_ST) >> 2);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDICPR_ST && daddr < ICDICPR_ED + 4) {
|
||||
assert((daddr-ICDICPR_ST) >> 2 < 32);
|
||||
pendingInt[(daddr-ICDICPR_ST) >> 2] &= ~pkt->get<uint32_t>();
|
||||
pendingInt[0] &= SGI_MASK; // Don't allow SGIs to be changed
|
||||
updateIntState((daddr-ICDICPR_ST) >> 2);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDIPR_ST && daddr < ICDIPR_ED + 4) {
|
||||
Addr int_num = daddr - ICDIPR_ST;
|
||||
assert(int_num < INT_LINES_MAX);
|
||||
uint8_t* int_p;
|
||||
if (int_num < (SGI_MAX + PPI_MAX))
|
||||
int_p = bankedIntPriority[ctx_id];
|
||||
else
|
||||
int_p = intPriority;
|
||||
uint32_t tmp;
|
||||
switch(pkt->getSize()) {
|
||||
case 1:
|
||||
tmp = pkt->get<uint8_t>();
|
||||
int_p[int_num] = bits(tmp, 7, 0);
|
||||
break;
|
||||
case 2:
|
||||
tmp = pkt->get<uint16_t>();
|
||||
int_p[int_num] = bits(tmp, 7, 0);
|
||||
int_p[int_num + 1] = bits(tmp, 15, 8);
|
||||
break;
|
||||
case 4:
|
||||
tmp = pkt->get<uint32_t>();
|
||||
int_p[int_num] = bits(tmp, 7, 0);
|
||||
int_p[int_num + 1] = bits(tmp, 15, 8);
|
||||
int_p[int_num + 2] = bits(tmp, 23, 16);
|
||||
int_p[int_num + 3] = bits(tmp, 31, 24);
|
||||
break;
|
||||
default:
|
||||
panic("Invalid size when writing to priority regs in Gic: %d\n",
|
||||
pkt->getSize());
|
||||
}
|
||||
|
||||
updateIntState(-1);
|
||||
updateRunPri();
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDIPTR_ST && daddr < ICDIPTR_ED + 4) {
|
||||
Addr int_num = (daddr-ICDIPTR_ST) ;
|
||||
assert(int_num < INT_LINES_MAX);
|
||||
// First 31 interrupts only target single processor
|
||||
if (int_num >= SGI_MAX) {
|
||||
if (pkt->getSize() == 1) {
|
||||
uint8_t tmp = pkt->get<uint8_t>();
|
||||
cpuTarget[int_num] = tmp & 0xff;
|
||||
} else {
|
||||
assert (pkt->getSize() == 4);
|
||||
int_num = mbits(int_num, 31, 2);
|
||||
uint32_t tmp = pkt->get<uint32_t>();
|
||||
cpuTarget[int_num] = bits(tmp, 7, 0);
|
||||
cpuTarget[int_num+1] = bits(tmp, 15, 8);
|
||||
cpuTarget[int_num+2] = bits(tmp, 23, 16);
|
||||
cpuTarget[int_num+3] = bits(tmp, 31, 24);
|
||||
}
|
||||
updateIntState((daddr-ICDIPTR_ST)>>2);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (daddr >= ICDICFR_ST && daddr < ICDICFR_ED + 4) {
|
||||
assert((daddr-ICDICFR_ST) >> 2 < 64);
|
||||
intConfig[(daddr-ICDICFR_ST)>>2] = pkt->get<uint32_t>();
|
||||
if (pkt->get<uint32_t>() & NN_CONFIG_MASK)
|
||||
warn("GIC N:N mode selected and not supported at this time\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch(daddr) {
|
||||
case ICDDCR:
|
||||
enabled = pkt->get<uint32_t>();
|
||||
DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled);
|
||||
break;
|
||||
case ICDSGIR:
|
||||
softInt(ctx_id, pkt->get<uint32_t>());
|
||||
break;
|
||||
default:
|
||||
panic("Tried to write Gic distributor at offset %#x\n", daddr);
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
pkt->makeAtomicResponse();
|
||||
return distPioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
Gic::writeCpu(PacketPtr pkt)
|
||||
{
|
||||
Addr daddr = pkt->getAddr() - cpuAddr;
|
||||
pkt->allocate();
|
||||
|
||||
assert(pkt->req->hasContextId());
|
||||
int ctx_id = pkt->req->contextId();
|
||||
IAR iar;
|
||||
|
||||
DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n",
|
||||
ctx_id, daddr, pkt->get<uint32_t>());
|
||||
|
||||
switch(daddr) {
|
||||
case ICCICR:
|
||||
cpuEnabled[ctx_id] = pkt->get<uint32_t>();
|
||||
break;
|
||||
case ICCPMR:
|
||||
cpuPriority[ctx_id] = pkt->get<uint32_t>();
|
||||
break;
|
||||
case ICCBPR:
|
||||
cpuBpr[ctx_id] = pkt->get<uint32_t>();
|
||||
break;
|
||||
case ICCEOIR:
|
||||
iar = pkt->get<uint32_t>();
|
||||
if (iar.ack_id < SGI_MAX) {
|
||||
// Clear out the bit that corrseponds to the cleared int
|
||||
uint64_t clr_int = ULL(1) << (ctx_id + 8 * iar.cpu_id);
|
||||
if (!(cpuSgiActive[iar.ack_id] & clr_int))
|
||||
panic("Done handling a SGI that isn't active?\n");
|
||||
cpuSgiActive[iar.ack_id] &= ~clr_int;
|
||||
} else if (iar.ack_id < (SGI_MAX + PPI_MAX) ) {
|
||||
uint32_t int_num = 1 << (iar.ack_id - SGI_MAX);
|
||||
if (!(cpuPpiActive[ctx_id] & int_num))
|
||||
panic("CPU %d Done handling a PPI interrupt that isn't active?\n", ctx_id);
|
||||
cpuPpiActive[ctx_id] &= ~int_num;
|
||||
} else {
|
||||
uint32_t int_num = 1 << intNumToBit(iar.ack_id);
|
||||
if (!(activeInt[intNumToWord(iar.ack_id)] & int_num))
|
||||
panic("Done handling interrupt that isn't active?\n");
|
||||
activeInt[intNumToWord(iar.ack_id)] &= ~int_num;
|
||||
}
|
||||
updateRunPri();
|
||||
DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
|
||||
ctx_id, iar.ack_id, iar.cpu_id);
|
||||
break;
|
||||
default:
|
||||
panic("Tried to write Gic cpu at offset %#x\n", daddr);
|
||||
break;
|
||||
}
|
||||
if (cpuEnabled[ctx_id]) updateIntState(-1);
|
||||
pkt->makeAtomicResponse();
|
||||
return cpuPioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
Gic::softInt(int ctx_id, SWI swi)
|
||||
{
|
||||
switch (swi.list_type) {
|
||||
case 1:
|
||||
// interrupt all
|
||||
uint8_t cpu_list;
|
||||
cpu_list = 0;
|
||||
for (int x = 0; x < CPU_MAX; x++)
|
||||
cpu_list |= cpuEnabled[x] ? 1 << x : 0;
|
||||
swi.cpu_list = cpu_list;
|
||||
break;
|
||||
case 2:
|
||||
// interrupt requesting cpu only
|
||||
swi.cpu_list = 1 << ctx_id;
|
||||
break;
|
||||
// else interrupt cpus specified
|
||||
}
|
||||
|
||||
DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx_id,
|
||||
swi.cpu_list);
|
||||
for (int i = 0; i < CPU_MAX; i++) {
|
||||
DPRINTF(IPI, "Processing CPU %d\n", i);
|
||||
if (!cpuEnabled[i])
|
||||
continue;
|
||||
if (swi.cpu_list & (1 << i))
|
||||
cpuSgiPending[swi.sgi_id] |= (1 << i) << (8 * ctx_id);
|
||||
DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id, cpuSgiPending[swi.sgi_id]);
|
||||
}
|
||||
updateIntState(-1);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
Gic::genSwiMask(int cpu)
|
||||
{
|
||||
if (cpu > 7)
|
||||
panic("Invalid CPU ID\n");
|
||||
return ULL(0x0101010101010101) << cpu;
|
||||
}
|
||||
|
||||
void
|
||||
Gic::updateIntState(int hint)
|
||||
{
|
||||
for (int cpu = 0; cpu < CPU_MAX; cpu++) {
|
||||
if (!cpuEnabled[cpu])
|
||||
continue;
|
||||
if (cpu >= sys->numContexts())
|
||||
break;
|
||||
|
||||
/*@todo use hint to do less work. */
|
||||
int highest_int = SPURIOUS_INT;
|
||||
// Priorities below that set in ICCPMR can be ignored
|
||||
uint8_t highest_pri = cpuPriority[cpu];
|
||||
|
||||
// Check SGIs
|
||||
for (int swi = 0; swi < SGI_MAX; swi++) {
|
||||
if (!cpuSgiPending[swi])
|
||||
continue;
|
||||
if (cpuSgiPending[swi] & genSwiMask(cpu))
|
||||
if (highest_pri > bankedIntPriority[cpu][swi]) {
|
||||
highest_pri = bankedIntPriority[cpu][swi];
|
||||
highest_int = swi;
|
||||
}
|
||||
}
|
||||
|
||||
// Check PPIs
|
||||
if (cpuPpiPending[cpu]) {
|
||||
for (int ppi = 0; ppi < PPI_MAX; ppi++) {
|
||||
if (cpuPpiPending[cpu] & (1 << ppi))
|
||||
if (highest_pri > bankedIntPriority[cpu][SGI_MAX + ppi]) {
|
||||
highest_pri = bankedIntPriority[cpu][SGI_MAX + ppi];
|
||||
highest_int = SGI_MAX + ppi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool mp_sys = sys->numRunningContexts() > 1;
|
||||
// Check other ints
|
||||
for (int x = 0; x < (itLines/INT_BITS_MAX); x++) {
|
||||
if (intEnabled[x] & pendingInt[x]) {
|
||||
for (int y = 0; y < INT_BITS_MAX; y++) {
|
||||
uint32_t int_nm = x * INT_BITS_MAX + y;
|
||||
DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm);
|
||||
/* Set current pending int as highest int for current cpu
|
||||
if the interrupt's priority higher than current prioirty
|
||||
and if currrent cpu is the target (for mp configs only)
|
||||
*/
|
||||
if ((bits(intEnabled[x], y) & bits(pendingInt[x], y)) &&
|
||||
(intPriority[int_nm] < highest_pri))
|
||||
if ( (!mp_sys) || (cpuTarget[int_nm] & (1 << cpu))) {
|
||||
highest_pri = intPriority[int_nm];
|
||||
highest_int = int_nm;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cpuHighestInt[cpu] = highest_int;
|
||||
|
||||
if (highest_int == SPURIOUS_INT)
|
||||
continue;
|
||||
|
||||
/* @todo make this work for more than one cpu, need to handle 1:N, N:N
|
||||
* models */
|
||||
if (enabled && cpuEnabled[cpu] && (highest_pri < cpuPriority[cpu]) &&
|
||||
!(activeInt[intNumToWord(highest_int)]
|
||||
& (1 << intNumToBit(highest_int)))) {
|
||||
|
||||
DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int,
|
||||
cpu);
|
||||
postInt(cpu, curTick() + intLatency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gic::updateRunPri()
|
||||
{
|
||||
for (int cpu = 0; cpu < CPU_MAX; cpu++) {
|
||||
if (!cpuEnabled[cpu])
|
||||
continue;
|
||||
uint8_t maxPriority = 0xff;
|
||||
for (int i = 0; i < itLines; i++){
|
||||
if (i < SGI_MAX) {
|
||||
if ((cpuSgiActive[i] & genSwiMask(cpu)) &&
|
||||
(bankedIntPriority[cpu][i] < maxPriority))
|
||||
maxPriority = bankedIntPriority[cpu][i];
|
||||
} else if (i < (SGI_MAX + PPI_MAX)) {
|
||||
if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) &&
|
||||
(bankedIntPriority[cpu][i] < maxPriority))
|
||||
maxPriority = bankedIntPriority[cpu][i];
|
||||
|
||||
} else {
|
||||
if (activeInt[intNumToWord(i)] & (1 << intNumToBit(i)))
|
||||
if (intPriority[i] < maxPriority)
|
||||
maxPriority = intPriority[i];
|
||||
}
|
||||
}
|
||||
iccrpr[cpu] = maxPriority;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gic::sendInt(uint32_t num)
|
||||
{
|
||||
DPRINTF(Interrupt, "Received Interupt number %d, cpuTarget %#x: \n",
|
||||
num, cpuTarget[num]);
|
||||
if (cpuTarget[num] & (cpuTarget[num] - 1))
|
||||
panic("Multiple targets for peripheral interrupts is not supported\n");
|
||||
pendingInt[intNumToWord(num)] |= 1 << intNumToBit(num);
|
||||
updateIntState(intNumToWord(num));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Gic::sendPPInt(uint32_t num, uint32_t cpu)
|
||||
{
|
||||
DPRINTF(Interrupt, "Received Interrupt number %d, cpuTarget %#x: \n",
|
||||
num, cpu);
|
||||
cpuPpiPending[cpu] |= 1 << (num - SGI_MAX);
|
||||
updateIntState(intNumToWord(num));
|
||||
}
|
||||
|
||||
void
|
||||
Gic::clearInt(uint32_t number)
|
||||
{
|
||||
/* @todo assume edge triggered only at the moment. Nothing to do. */
|
||||
}
|
||||
|
||||
void
|
||||
Gic::postInt(uint32_t cpu, Tick when)
|
||||
{
|
||||
if (!(postIntEvent[cpu]->scheduled()))
|
||||
eventq->schedule(postIntEvent[cpu], when);
|
||||
}
|
||||
|
||||
AddrRangeList
|
||||
Gic::getAddrRanges()
|
||||
{
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(distAddr, DIST_SIZE));
|
||||
ranges.push_back(RangeSize(cpuAddr, CPU_SIZE));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Gic::serialize(std::ostream &os)
|
||||
{
|
||||
DPRINTF(Checkpoint, "Serializing Arm GIC\n");
|
||||
|
||||
SERIALIZE_SCALAR(distAddr);
|
||||
SERIALIZE_SCALAR(cpuAddr);
|
||||
SERIALIZE_SCALAR(distPioDelay);
|
||||
SERIALIZE_SCALAR(cpuPioDelay);
|
||||
SERIALIZE_SCALAR(enabled);
|
||||
SERIALIZE_SCALAR(itLines);
|
||||
SERIALIZE_SCALAR(itLinesLog2);
|
||||
SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX);
|
||||
SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX);
|
||||
SERIALIZE_ARRAY(activeInt, INT_BITS_MAX);
|
||||
SERIALIZE_ARRAY(iccrpr, CPU_MAX);
|
||||
SERIALIZE_ARRAY(intPriority, INT_LINES_MAX);
|
||||
SERIALIZE_ARRAY(cpuTarget, INT_LINES_MAX);
|
||||
SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
|
||||
SERIALIZE_ARRAY(cpuEnabled, CPU_MAX);
|
||||
SERIALIZE_ARRAY(cpuPriority, CPU_MAX);
|
||||
SERIALIZE_ARRAY(cpuBpr, CPU_MAX);
|
||||
SERIALIZE_ARRAY(cpuHighestInt, CPU_MAX);
|
||||
SERIALIZE_ARRAY(cpuSgiActive, SGI_MAX);
|
||||
SERIALIZE_ARRAY(cpuSgiPending, SGI_MAX);
|
||||
SERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
|
||||
SERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
|
||||
SERIALIZE_ARRAY(*bankedIntPriority, CPU_MAX * (SGI_MAX + PPI_MAX));
|
||||
SERIALIZE_SCALAR(irqEnable);
|
||||
Tick interrupt_time[CPU_MAX];
|
||||
for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
|
||||
interrupt_time[cpu] = 0;
|
||||
if (postIntEvent[cpu]->scheduled()) {
|
||||
interrupt_time[cpu] = postIntEvent[cpu]->when();
|
||||
}
|
||||
}
|
||||
SERIALIZE_ARRAY(interrupt_time, CPU_MAX);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Gic::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
DPRINTF(Checkpoint, "Unserializing Arm GIC\n");
|
||||
|
||||
UNSERIALIZE_SCALAR(distAddr);
|
||||
UNSERIALIZE_SCALAR(cpuAddr);
|
||||
UNSERIALIZE_SCALAR(distPioDelay);
|
||||
UNSERIALIZE_SCALAR(cpuPioDelay);
|
||||
UNSERIALIZE_SCALAR(enabled);
|
||||
UNSERIALIZE_SCALAR(itLines);
|
||||
UNSERIALIZE_SCALAR(itLinesLog2);
|
||||
UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX);
|
||||
UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX);
|
||||
UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX);
|
||||
UNSERIALIZE_ARRAY(iccrpr, CPU_MAX);
|
||||
UNSERIALIZE_ARRAY(intPriority, INT_LINES_MAX);
|
||||
UNSERIALIZE_ARRAY(cpuTarget, INT_LINES_MAX);
|
||||
UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
|
||||
UNSERIALIZE_ARRAY(cpuEnabled, CPU_MAX);
|
||||
UNSERIALIZE_ARRAY(cpuPriority, CPU_MAX);
|
||||
UNSERIALIZE_ARRAY(cpuBpr, CPU_MAX);
|
||||
UNSERIALIZE_ARRAY(cpuHighestInt, CPU_MAX);
|
||||
UNSERIALIZE_ARRAY(cpuSgiActive, SGI_MAX);
|
||||
UNSERIALIZE_ARRAY(cpuSgiPending, SGI_MAX);
|
||||
UNSERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
|
||||
UNSERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
|
||||
UNSERIALIZE_ARRAY(*bankedIntPriority, CPU_MAX * (SGI_MAX + PPI_MAX));
|
||||
UNSERIALIZE_SCALAR(irqEnable);
|
||||
|
||||
Tick interrupt_time[CPU_MAX];
|
||||
UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX);
|
||||
|
||||
for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
|
||||
if (interrupt_time[cpu])
|
||||
schedule(postIntEvent[cpu], interrupt_time[cpu]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Gic *
|
||||
GicParams::create()
|
||||
{
|
||||
return new Gic(this);
|
||||
}
|
||||
|
||||
/* Functions for debugging and testing */
|
||||
void
|
||||
Gic::driveSPI(unsigned int spiVect)
|
||||
{
|
||||
DPRINTF(GIC, "Received SPI Vector:%x Enable: %d\n", spiVect, irqEnable);
|
||||
pendingInt[1] |= spiVect;
|
||||
if (irqEnable && enabled) {
|
||||
updateIntState(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gic::driveIrqEn( bool state)
|
||||
{
|
||||
irqEnable = state;
|
||||
DPRINTF(GIC, " Enabling Irq\n");
|
||||
updateIntState(-1);
|
||||
}
|
||||
|
||||
void
|
||||
Gic::driveLegIRQ(bool state)
|
||||
{
|
||||
if (irqEnable && !(!enabled && cpuEnabled[0])) {
|
||||
if (state) {
|
||||
DPRINTF(GIC, "Driving Legacy Irq\n");
|
||||
platform->intrctrl->post(0, ArmISA::INT_IRQ, 0);
|
||||
}
|
||||
else platform->intrctrl->clear(0, ArmISA::INT_IRQ, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gic::driveLegFIQ(bool state)
|
||||
{
|
||||
if (state)
|
||||
platform->intrctrl->post(0, ArmISA::INT_FIQ, 0);
|
||||
else platform->intrctrl->clear(0, ArmISA::INT_FIQ, 0);
|
||||
}
|
||||
321
simulators/gem5/src/dev/arm/gic.hh
Normal file
321
simulators/gem5/src/dev/arm/gic.hh
Normal file
@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 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
|
||||
* Implementiation of a PL390 GIC
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_GIC_H__
|
||||
#define __DEV_ARM_GIC_H__
|
||||
|
||||
#include "base/bitunion.hh"
|
||||
#include "base/range.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "dev/platform.hh"
|
||||
#include "cpu/intr_control.hh"
|
||||
#include "params/Gic.hh"
|
||||
|
||||
/** @todo this code only assumes one processor for now. Low word
|
||||
* of intEnabled and pendingInt need to be replicated per CPU.
|
||||
* bottom 31 interrupts (7 words) need to be replicated for
|
||||
* for interrupt priority register, processor target registers
|
||||
* interrupt config registers */
|
||||
|
||||
class Gic : public PioDevice
|
||||
{
|
||||
protected:
|
||||
// distributor memory addresses
|
||||
static const int ICDDCR = 0x000; // control register
|
||||
static const int ICDICTR = 0x004; // controller type
|
||||
static const int ICDIIDR = 0x008; // implementer id
|
||||
static const int ICDISER_ST = 0x100; // interrupt set enable
|
||||
static const int ICDISER_ED = 0x17c;
|
||||
static const int ICDICER_ST = 0x180; // interrupt clear enable
|
||||
static const int ICDICER_ED = 0x1fc;
|
||||
static const int ICDISPR_ST = 0x200; // set pending interrupt
|
||||
static const int ICDISPR_ED = 0x27c;
|
||||
static const int ICDICPR_ST = 0x280; // clear pending interrupt
|
||||
static const int ICDICPR_ED = 0x2fc;
|
||||
static const int ICDABR_ST = 0x300; // active bit registers
|
||||
static const int ICDABR_ED = 0x37c;
|
||||
static const int ICDIPR_ST = 0x400; // interrupt priority registers
|
||||
static const int ICDIPR_ED = 0x7f8;
|
||||
static const int ICDIPTR_ST = 0x800; // processor target registers
|
||||
static const int ICDIPTR_ED = 0xbf8;
|
||||
static const int ICDICFR_ST = 0xc00; // interrupt config registers
|
||||
static const int ICDICFR_ED = 0xcfc;
|
||||
static const int ICDSGIR = 0xf00; // software generated interrupt
|
||||
static const int DIST_SIZE = 0xfff;
|
||||
|
||||
// cpu memory addressesa
|
||||
static const int ICCICR = 0x00; // CPU control register
|
||||
static const int ICCPMR = 0x04; // Interrupt priority mask
|
||||
static const int ICCBPR = 0x08; // binary point register
|
||||
static const int ICCIAR = 0x0C; // interrupt ack register
|
||||
static const int ICCEOIR = 0x10; // end of interrupt
|
||||
static const int ICCRPR = 0x14; // runing priority
|
||||
static const int ICCHPIR = 0x18; // highest pending interrupt
|
||||
static const int ICCABPR = 0x1c; // aliased binary point
|
||||
static const int ICCIIDR = 0xfc; // cpu interface id register
|
||||
static const int CPU_SIZE = 0xff;
|
||||
|
||||
static const int SGI_MAX = 16; // Number of Software Gen Interrupts
|
||||
static const int PPI_MAX = 16; // Number of Private Peripheral Interrupts
|
||||
|
||||
/** Mask off SGI's when setting/clearing pending bits */
|
||||
static const int SGI_MASK = 0xFFFF0000;
|
||||
|
||||
/** Mask for bits that config N:N mode in ICDICFR's */
|
||||
static const int NN_CONFIG_MASK = 0x55555555;
|
||||
|
||||
static const int CPU_MAX = 8; // Max number of supported CPU interfaces
|
||||
static const int SPURIOUS_INT = 1023;
|
||||
static const int INT_BITS_MAX = 32;
|
||||
static const int INT_LINES_MAX = 1020;
|
||||
|
||||
BitUnion32(SWI)
|
||||
Bitfield<3,0> sgi_id;
|
||||
Bitfield<23,16> cpu_list;
|
||||
Bitfield<25,24> list_type;
|
||||
EndBitUnion(SWI)
|
||||
|
||||
BitUnion32(IAR)
|
||||
Bitfield<9,0> ack_id;
|
||||
Bitfield<12,10> cpu_id;
|
||||
EndBitUnion(IAR)
|
||||
|
||||
Platform *platform;
|
||||
|
||||
/** Distributor address GIC listens at */
|
||||
Addr distAddr;
|
||||
|
||||
/** CPU address GIC listens at */
|
||||
/** @todo is this one per cpu? */
|
||||
Addr cpuAddr;
|
||||
|
||||
/** Latency for a distributor operation */
|
||||
Tick distPioDelay;
|
||||
|
||||
/** Latency for a cpu operation */
|
||||
Tick cpuPioDelay;
|
||||
|
||||
/** Latency for a interrupt to get to CPU */
|
||||
Tick intLatency;
|
||||
|
||||
/** Gic enabled */
|
||||
bool enabled;
|
||||
|
||||
/** Number of itLines enabled */
|
||||
uint32_t itLines;
|
||||
|
||||
uint32_t itLinesLog2;
|
||||
|
||||
/** interrupt enable bits for all possible 1020 interupts.
|
||||
* one bit per interrupt, 32 bit per word = 32 words */
|
||||
uint32_t intEnabled[INT_BITS_MAX];
|
||||
|
||||
/** interrupt pending bits for all possible 1020 interupts.
|
||||
* one bit per interrupt, 32 bit per word = 32 words */
|
||||
uint32_t pendingInt[INT_BITS_MAX];
|
||||
|
||||
/** interrupt active bits for all possible 1020 interupts.
|
||||
* one bit per interrupt, 32 bit per word = 32 words */
|
||||
uint32_t activeInt[INT_BITS_MAX];
|
||||
|
||||
/** read only running priroity register, 1 per cpu*/
|
||||
uint32_t iccrpr[CPU_MAX];
|
||||
|
||||
/** an 8 bit priority (lower is higher priority) for each
|
||||
* of the 1020 possible supported interrupts.
|
||||
*/
|
||||
uint8_t intPriority[INT_LINES_MAX];
|
||||
|
||||
/** an 8 bit cpu target id for each shared peripheral interrupt
|
||||
* of the 1020 possible supported interrupts.
|
||||
*/
|
||||
uint8_t cpuTarget[INT_LINES_MAX];
|
||||
|
||||
/** 2 bit per interrupt signaling if it's level or edge sensitive
|
||||
* and if it is 1:N or N:N */
|
||||
uint32_t intConfig[INT_BITS_MAX*2];
|
||||
|
||||
/** CPU enabled */
|
||||
bool cpuEnabled[CPU_MAX];
|
||||
|
||||
/** CPU priority */
|
||||
uint8_t cpuPriority[CPU_MAX];
|
||||
|
||||
/** Binary point registers */
|
||||
uint8_t cpuBpr[CPU_MAX];
|
||||
|
||||
/** highest interrupt that is interrupting CPU */
|
||||
uint32_t cpuHighestInt[CPU_MAX];
|
||||
|
||||
/** One bit per cpu per software interrupt that is pending for each possible
|
||||
* sgi source. Indexed by SGI number. Each byte in generating cpu id and
|
||||
* bits in position is destination id. e.g. 0x4 = CPU 0 generated interrupt
|
||||
* for CPU 2. */
|
||||
uint64_t cpuSgiPending[SGI_MAX];
|
||||
uint64_t cpuSgiActive[SGI_MAX];
|
||||
|
||||
/** One bit per private peripheral interrupt. Only upper 16 bits
|
||||
* will be used since PPI interrupts are numberred from 16 to 32 */
|
||||
uint32_t cpuPpiPending[CPU_MAX];
|
||||
uint32_t cpuPpiActive[CPU_MAX];
|
||||
|
||||
/** Banked interrupt prioirty registers for SGIs and PPIs */
|
||||
uint8_t bankedIntPriority[CPU_MAX][SGI_MAX + PPI_MAX];
|
||||
|
||||
/** IRQ Enable Used for debug */
|
||||
bool irqEnable;
|
||||
|
||||
/** software generated interrupt
|
||||
* @param data data to decode that indicates which cpus to interrupt
|
||||
*/
|
||||
void softInt(int ctx_id, SWI swi);
|
||||
|
||||
/** See if some processor interrupt flags need to be enabled/disabled
|
||||
* @param hint which set of interrupts needs to be checked
|
||||
*/
|
||||
void updateIntState(int hint);
|
||||
|
||||
/** Update the register that records priority of the highest priority
|
||||
* active interrupt*/
|
||||
void updateRunPri();
|
||||
|
||||
/** generate a bit mask to check cpuSgi for an interrupt. */
|
||||
uint64_t genSwiMask(int cpu);
|
||||
|
||||
int intNumToWord(int num) const { return num >> 5; }
|
||||
int intNumToBit(int num) const { return num % 32; }
|
||||
|
||||
/** Post an interrupt to a CPU
|
||||
*/
|
||||
void postInt(uint32_t cpu, Tick when);
|
||||
|
||||
/** Event definition to post interrupt to CPU after a delay
|
||||
*/
|
||||
class PostIntEvent : public Event
|
||||
{
|
||||
private:
|
||||
uint32_t cpu;
|
||||
Platform *platform;
|
||||
public:
|
||||
PostIntEvent( uint32_t c, Platform* p)
|
||||
: cpu(c), platform(p)
|
||||
{ }
|
||||
void process() { platform->intrctrl->post(cpu, ArmISA::INT_IRQ, 0);}
|
||||
const char *description() const { return "Post Interrupt to CPU"; }
|
||||
};
|
||||
PostIntEvent *postIntEvent[CPU_MAX];
|
||||
|
||||
public:
|
||||
typedef GicParams Params;
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
Gic(const Params *p);
|
||||
|
||||
/** Return the address ranges used by the Gic
|
||||
* This is the distributor address + all cpu addresses
|
||||
*/
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
/** A PIO read to the device, immediately split up into
|
||||
* readDistributor() or readCpu()
|
||||
*/
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
|
||||
/** A PIO read to the device, immediately split up into
|
||||
* writeDistributor() or writeCpu()
|
||||
*/
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
/** Handle a read to the distributor poriton of the GIC
|
||||
* @param pkt packet to respond to
|
||||
*/
|
||||
Tick readDistributor(PacketPtr pkt);
|
||||
|
||||
/** Handle a read to the cpu poriton of the GIC
|
||||
* @param pkt packet to respond to
|
||||
*/
|
||||
Tick readCpu(PacketPtr pkt);
|
||||
|
||||
/** Handle a write to the distributor poriton of the GIC
|
||||
* @param pkt packet to respond to
|
||||
*/
|
||||
Tick writeDistributor(PacketPtr pkt);
|
||||
|
||||
/** Handle a write to the cpu poriton of the GIC
|
||||
* @param pkt packet to respond to
|
||||
*/
|
||||
Tick writeCpu(PacketPtr pkt);
|
||||
|
||||
/** Post an interrupt from a device that is connected to the Gic.
|
||||
* Depending on the configuration, the gic will pass this interrupt
|
||||
* on through to a CPU.
|
||||
* @param number number of interrupt to send */
|
||||
void sendInt(uint32_t number);
|
||||
|
||||
/** Interface call for private peripheral interrupts */
|
||||
void sendPPInt(uint32_t num, uint32_t cpu);
|
||||
|
||||
/** Clear an interrupt from a device that is connected to the Gic
|
||||
* Depending on the configuration, the gic may de-assert it's cpu line
|
||||
* @param number number of interrupt to send */
|
||||
void clearInt(uint32_t number);
|
||||
|
||||
/* Various functions fer testing and debugging */
|
||||
void driveSPI(uint32_t spi);
|
||||
void driveLegIRQ(bool state);
|
||||
void driveLegFIQ(bool state);
|
||||
void driveIrqEn(bool state);
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
};
|
||||
|
||||
#endif //__DEV_ARM_GIC_H__
|
||||
371
simulators/gem5/src/dev/arm/kmi.cc
Normal file
371
simulators/gem5/src/dev/arm/kmi.cc
Normal file
@ -0,0 +1,371 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 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
|
||||
* William Wang
|
||||
*/
|
||||
|
||||
#include "base/vnc/vncserver.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/Pl050.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "dev/arm/kmi.hh"
|
||||
#include "dev/ps2.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
Pl050::Pl050(const Params *p)
|
||||
: AmbaIntDevice(p), control(0), status(0x43), clkdiv(0), interrupts(0),
|
||||
rawInterrupts(0), ackNext(false), shiftDown(false), vnc(p->vnc),
|
||||
driverInitialized(false), intEvent(this)
|
||||
{
|
||||
pioSize = 0xfff;
|
||||
|
||||
if (vnc) {
|
||||
if (!p->is_mouse)
|
||||
vnc->setKeyboard(this);
|
||||
else
|
||||
vnc->setMouse(this);
|
||||
}
|
||||
}
|
||||
|
||||
Tick
|
||||
Pl050::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
|
||||
|
||||
uint32_t data = 0;
|
||||
|
||||
switch (daddr) {
|
||||
case kmiCr:
|
||||
DPRINTF(Pl050, "Read Commmand: %#x\n", (uint32_t)control);
|
||||
data = control;
|
||||
break;
|
||||
case kmiStat:
|
||||
if (rxQueue.empty())
|
||||
status.rxfull = 0;
|
||||
else
|
||||
status.rxfull = 1;
|
||||
|
||||
DPRINTF(Pl050, "Read Status: %#x\n", (uint32_t)status);
|
||||
data = status;
|
||||
break;
|
||||
case kmiData:
|
||||
if (rxQueue.empty()) {
|
||||
data = 0;
|
||||
} else {
|
||||
data = rxQueue.front();
|
||||
rxQueue.pop_front();
|
||||
}
|
||||
DPRINTF(Pl050, "Read Data: %#x\n", (uint32_t)data);
|
||||
updateIntStatus();
|
||||
break;
|
||||
case kmiClkDiv:
|
||||
data = clkdiv;
|
||||
break;
|
||||
case kmiISR:
|
||||
data = interrupts;
|
||||
DPRINTF(Pl050, "Read Interrupts: %#x\n", (uint32_t)interrupts);
|
||||
break;
|
||||
default:
|
||||
if (AmbaDev::readId(pkt, ambaId, pioAddr)) {
|
||||
// Hack for variable size accesses
|
||||
data = pkt->get<uint32_t>();
|
||||
break;
|
||||
}
|
||||
|
||||
warn("Tried to read PL050 at offset %#x that doesn't exist\n", daddr);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(pkt->getSize()) {
|
||||
case 1:
|
||||
pkt->set<uint8_t>(data);
|
||||
break;
|
||||
case 2:
|
||||
pkt->set<uint16_t>(data);
|
||||
break;
|
||||
case 4:
|
||||
pkt->set<uint32_t>(data);
|
||||
break;
|
||||
default:
|
||||
panic("KMI read size too big?\n");
|
||||
break;
|
||||
}
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
Pl050::write(PacketPtr pkt)
|
||||
{
|
||||
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
assert(pkt->getSize() == sizeof(uint8_t));
|
||||
|
||||
|
||||
switch (daddr) {
|
||||
case kmiCr:
|
||||
DPRINTF(Pl050, "Write Commmand: %#x\n", (uint32_t)pkt->get<uint8_t>());
|
||||
control = pkt->get<uint8_t>();
|
||||
updateIntStatus();
|
||||
break;
|
||||
case kmiData:
|
||||
DPRINTF(Pl050, "Write Data: %#x\n", (uint32_t)pkt->get<uint8_t>());
|
||||
processCommand(pkt->get<uint8_t>());
|
||||
updateIntStatus();
|
||||
break;
|
||||
case kmiClkDiv:
|
||||
clkdiv = pkt->get<uint8_t>();
|
||||
break;
|
||||
default:
|
||||
warn("Tried to write PL050 at offset %#x that doesn't exist\n", daddr);
|
||||
break;
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
Pl050::processCommand(uint8_t byte)
|
||||
{
|
||||
using namespace Ps2;
|
||||
|
||||
if (ackNext) {
|
||||
ackNext--;
|
||||
rxQueue.push_back(Ack);
|
||||
updateIntStatus();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (byte) {
|
||||
case Ps2Reset:
|
||||
rxQueue.push_back(Ack);
|
||||
rxQueue.push_back(SelfTestPass);
|
||||
break;
|
||||
case SetResolution:
|
||||
case SetRate:
|
||||
case SetStatusLed:
|
||||
case SetScaling1_1:
|
||||
case SetScaling1_2:
|
||||
rxQueue.push_back(Ack);
|
||||
ackNext = 1;
|
||||
break;
|
||||
case ReadId:
|
||||
rxQueue.push_back(Ack);
|
||||
if (params()->is_mouse)
|
||||
rxQueue.push_back(MouseId);
|
||||
else
|
||||
rxQueue.push_back(KeyboardId);
|
||||
break;
|
||||
case TpReadId:
|
||||
if (!params()->is_mouse)
|
||||
break;
|
||||
// We're not a trackpoint device, this should make the probe go away
|
||||
rxQueue.push_back(Ack);
|
||||
rxQueue.push_back(0);
|
||||
rxQueue.push_back(0);
|
||||
// fall through
|
||||
case Disable:
|
||||
case Enable:
|
||||
case SetDefaults:
|
||||
rxQueue.push_back(Ack);
|
||||
break;
|
||||
case StatusRequest:
|
||||
rxQueue.push_back(Ack);
|
||||
rxQueue.push_back(0);
|
||||
rxQueue.push_back(2); // default resolution
|
||||
rxQueue.push_back(100); // default sample rate
|
||||
break;
|
||||
case TouchKitId:
|
||||
ackNext = 2;
|
||||
rxQueue.push_back(Ack);
|
||||
rxQueue.push_back(TouchKitId);
|
||||
rxQueue.push_back(1);
|
||||
rxQueue.push_back('A');
|
||||
|
||||
driverInitialized = true;
|
||||
break;
|
||||
default:
|
||||
panic("Unknown byte received: %d\n", byte);
|
||||
}
|
||||
|
||||
updateIntStatus();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pl050::updateIntStatus()
|
||||
{
|
||||
if (!rxQueue.empty())
|
||||
rawInterrupts.rx = 1;
|
||||
else
|
||||
rawInterrupts.rx = 0;
|
||||
|
||||
interrupts.tx = rawInterrupts.tx & control.txint_enable;
|
||||
interrupts.rx = rawInterrupts.rx & control.rxint_enable;
|
||||
|
||||
DPRINTF(Pl050, "rawInterupts=%#x control=%#x interrupts=%#x\n",
|
||||
(uint32_t)rawInterrupts, (uint32_t)control, (uint32_t)interrupts);
|
||||
|
||||
if (interrupts && !intEvent.scheduled())
|
||||
schedule(intEvent, curTick() + intDelay);
|
||||
}
|
||||
|
||||
void
|
||||
Pl050::generateInterrupt()
|
||||
{
|
||||
|
||||
if (interrupts) {
|
||||
gic->sendInt(intNum);
|
||||
DPRINTF(Pl050, "Generated interrupt\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pl050::mouseAt(uint16_t x, uint16_t y, uint8_t buttons)
|
||||
{
|
||||
using namespace Ps2;
|
||||
|
||||
// If the driver hasn't initialized the device yet, no need to try and send
|
||||
// it anything. Similarly we can get vnc mouse events orders of maginture
|
||||
// faster than m5 can process them. Only queue up two sets mouse movements
|
||||
// and don't add more until those are processed.
|
||||
if (!driverInitialized || rxQueue.size() > 10)
|
||||
return;
|
||||
|
||||
// We shouldn't be here unless a vnc server called us in which case
|
||||
// we should have a pointer to it
|
||||
assert(vnc);
|
||||
|
||||
// Convert screen coordinates to touchpad coordinates
|
||||
uint16_t _x = (2047.0/vnc->videoWidth()) * x;
|
||||
uint16_t _y = (2047.0/vnc->videoHeight()) * y;
|
||||
|
||||
rxQueue.push_back(buttons);
|
||||
rxQueue.push_back(_x >> 7);
|
||||
rxQueue.push_back(_x & 0x7f);
|
||||
rxQueue.push_back(_y >> 7);
|
||||
rxQueue.push_back(_y & 0x7f);
|
||||
|
||||
updateIntStatus();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pl050::keyPress(uint32_t key, bool down)
|
||||
{
|
||||
using namespace Ps2;
|
||||
|
||||
std::list<uint8_t> keys;
|
||||
|
||||
// convert the X11 keysym into ps2 codes
|
||||
keySymToPs2(key, down, shiftDown, keys);
|
||||
|
||||
// Insert into our queue of charecters
|
||||
rxQueue.splice(rxQueue.end(), keys);
|
||||
updateIntStatus();
|
||||
}
|
||||
|
||||
void
|
||||
Pl050::serialize(std::ostream &os)
|
||||
{
|
||||
uint8_t ctrlreg = control;
|
||||
SERIALIZE_SCALAR(ctrlreg);
|
||||
|
||||
uint8_t stsreg = status;
|
||||
SERIALIZE_SCALAR(stsreg);
|
||||
SERIALIZE_SCALAR(clkdiv);
|
||||
|
||||
uint8_t ints = interrupts;
|
||||
SERIALIZE_SCALAR(ints);
|
||||
|
||||
uint8_t raw_ints = rawInterrupts;
|
||||
SERIALIZE_SCALAR(raw_ints);
|
||||
|
||||
SERIALIZE_SCALAR(ackNext);
|
||||
SERIALIZE_SCALAR(shiftDown);
|
||||
SERIALIZE_SCALAR(driverInitialized);
|
||||
|
||||
arrayParamOut(os, "rxQueue", rxQueue);
|
||||
}
|
||||
|
||||
void
|
||||
Pl050::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
uint8_t ctrlreg;
|
||||
UNSERIALIZE_SCALAR(ctrlreg);
|
||||
control = ctrlreg;
|
||||
|
||||
uint8_t stsreg;
|
||||
UNSERIALIZE_SCALAR(stsreg);
|
||||
status = stsreg;
|
||||
|
||||
UNSERIALIZE_SCALAR(clkdiv);
|
||||
|
||||
uint8_t ints;
|
||||
UNSERIALIZE_SCALAR(ints);
|
||||
interrupts = ints;
|
||||
|
||||
uint8_t raw_ints;
|
||||
UNSERIALIZE_SCALAR(raw_ints);
|
||||
rawInterrupts = raw_ints;
|
||||
|
||||
UNSERIALIZE_SCALAR(ackNext);
|
||||
UNSERIALIZE_SCALAR(shiftDown);
|
||||
UNSERIALIZE_SCALAR(driverInitialized);
|
||||
|
||||
arrayParamIn(cp, section, "rxQueue", rxQueue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Pl050 *
|
||||
Pl050Params::create()
|
||||
{
|
||||
return new Pl050(this);
|
||||
}
|
||||
167
simulators/gem5/src/dev/arm/kmi.hh
Normal file
167
simulators/gem5/src/dev/arm/kmi.hh
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 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: William Wang
|
||||
*/
|
||||
|
||||
|
||||
/** @file
|
||||
* Implementiation of a PL050 KMI
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_PL050_HH__
|
||||
#define __DEV_ARM_PL050_HH__
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "base/vnc/vncserver.hh"
|
||||
#include "base/range.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "params/Pl050.hh"
|
||||
|
||||
class Gic;
|
||||
|
||||
class Pl050 : public AmbaIntDevice, public VncKeyboard, public VncMouse
|
||||
{
|
||||
protected:
|
||||
static const int kmiCr = 0x000;
|
||||
static const int kmiStat = 0x004;
|
||||
static const int kmiData = 0x008;
|
||||
static const int kmiClkDiv = 0x00C;
|
||||
static const int kmiISR = 0x010;
|
||||
|
||||
BitUnion8(ControlReg)
|
||||
Bitfield<0> force_clock_low;
|
||||
Bitfield<1> force_data_low;
|
||||
Bitfield<2> enable;
|
||||
Bitfield<3> txint_enable;
|
||||
Bitfield<4> rxint_enable;
|
||||
Bitfield<5> type;
|
||||
EndBitUnion(ControlReg)
|
||||
|
||||
/** control register
|
||||
*/
|
||||
ControlReg control;
|
||||
|
||||
/** KMI status register */
|
||||
BitUnion8(StatusReg)
|
||||
Bitfield<0> data_in;
|
||||
Bitfield<1> clk_in;
|
||||
Bitfield<2> rxparity;
|
||||
Bitfield<3> rxbusy;
|
||||
Bitfield<4> rxfull;
|
||||
Bitfield<5> txbusy;
|
||||
Bitfield<6> txempty;
|
||||
EndBitUnion(StatusReg)
|
||||
|
||||
StatusReg status;
|
||||
|
||||
/** clock divisor register
|
||||
* This register is just kept around to satisfy reads after driver does
|
||||
* writes. The divsor does nothing, as we're not actually signaling ps2
|
||||
* serial commands to anything.
|
||||
*/
|
||||
uint8_t clkdiv;
|
||||
|
||||
BitUnion8(InterruptReg)
|
||||
Bitfield<0> rx;
|
||||
Bitfield<1> tx;
|
||||
EndBitUnion(InterruptReg)
|
||||
|
||||
/** interrupt status register. */
|
||||
InterruptReg interrupts;
|
||||
|
||||
/** raw interrupt register (unmasked) */
|
||||
InterruptReg rawInterrupts;
|
||||
|
||||
/** If the controller should ignore the next data byte and acknowledge it.
|
||||
* The driver is attempting to setup some feature we don't care about
|
||||
*/
|
||||
int ackNext;
|
||||
|
||||
/** is the shift key currently down */
|
||||
bool shiftDown;
|
||||
|
||||
/** The vnc server we're connected to (if any) */
|
||||
VncServer *vnc;
|
||||
|
||||
/** If the linux driver has initialized the device yet and thus can we send
|
||||
* mouse data */
|
||||
bool driverInitialized;
|
||||
|
||||
/** Update the status of the interrupt registers and schedule an interrupt
|
||||
* if required */
|
||||
void updateIntStatus();
|
||||
|
||||
/** Function to generate interrupt */
|
||||
void generateInterrupt();
|
||||
|
||||
/** Wrapper to create an event out of the thing */
|
||||
EventWrapper<Pl050, &Pl050::generateInterrupt> intEvent;
|
||||
|
||||
/** Receive queue. This list contains all the pending commands that
|
||||
* need to be sent to the driver
|
||||
*/
|
||||
std::list<uint8_t> rxQueue;
|
||||
|
||||
/** Handle a command sent to the kmi and respond appropriately
|
||||
*/
|
||||
void processCommand(uint8_t byte);
|
||||
|
||||
public:
|
||||
typedef Pl050Params Params;
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
Pl050(const Params *p);
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
virtual void mouseAt(uint16_t x, uint16_t y, uint8_t buttons);
|
||||
virtual void keyPress(uint32_t key, bool down);
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
#endif // __DEV_ARM_PL050_HH__
|
||||
331
simulators/gem5/src/dev/arm/pl011.cc
Normal file
331
simulators/gem5/src/dev/arm/pl011.cc
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 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
|
||||
*/
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "debug/Checkpoint.hh"
|
||||
#include "debug/Uart.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "dev/arm/gic.hh"
|
||||
#include "dev/arm/pl011.hh"
|
||||
#include "dev/terminal.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "sim/sim_exit.hh"
|
||||
|
||||
Pl011::Pl011(const Params *p)
|
||||
: Uart(p), control(0x300), fbrd(0), ibrd(0), lcrh(0), ifls(0x12), imsc(0),
|
||||
rawInt(0), maskInt(0), intNum(p->int_num), gic(p->gic),
|
||||
endOnEOT(p->end_on_eot), intDelay(p->int_delay), intEvent(this)
|
||||
{
|
||||
pioSize = 0xfff;
|
||||
}
|
||||
|
||||
Tick
|
||||
Pl011::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
|
||||
DPRINTF(Uart, " read register %#x size=%d\n", daddr, pkt->getSize());
|
||||
|
||||
// use a temporary data since the uart registers are read/written with
|
||||
// different size operations
|
||||
//
|
||||
uint32_t data = 0;
|
||||
|
||||
switch(daddr) {
|
||||
case UART_DR:
|
||||
data = 0;
|
||||
if (term->dataAvailable())
|
||||
data = term->in();
|
||||
break;
|
||||
case UART_FR:
|
||||
// For now we're infintely fast, so TX is never full, always empty,
|
||||
// always clear to send
|
||||
data = UART_FR_TXFE | UART_FR_CTS;
|
||||
if (!term->dataAvailable())
|
||||
data |= UART_FR_RXFE;
|
||||
DPRINTF(Uart, "Reading FR register as %#x rawInt=0x%x imsc=0x%x maskInt=0x%x\n",
|
||||
data, rawInt, imsc, maskInt);
|
||||
break;
|
||||
case UART_CR:
|
||||
data = control;
|
||||
break;
|
||||
case UART_IBRD:
|
||||
data = ibrd;
|
||||
break;
|
||||
case UART_FBRD:
|
||||
data = fbrd;
|
||||
break;
|
||||
case UART_LCRH:
|
||||
data = lcrh;
|
||||
break;
|
||||
case UART_IFLS:
|
||||
data = ifls;
|
||||
break;
|
||||
case UART_IMSC:
|
||||
data = imsc;
|
||||
break;
|
||||
case UART_RIS:
|
||||
data = rawInt;
|
||||
DPRINTF(Uart, "Reading Raw Int status as 0x%x\n", rawInt);
|
||||
break;
|
||||
case UART_MIS:
|
||||
DPRINTF(Uart, "Reading Masked Int status as 0x%x\n", rawInt);
|
||||
data = maskInt;
|
||||
break;
|
||||
default:
|
||||
if (AmbaDev::readId(pkt, AMBA_ID, pioAddr)) {
|
||||
// Hack for variable size accesses
|
||||
data = pkt->get<uint32_t>();
|
||||
break;
|
||||
}
|
||||
|
||||
panic("Tried to read PL011 at offset %#x that doesn't exist\n", daddr);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(pkt->getSize()) {
|
||||
case 1:
|
||||
pkt->set<uint8_t>(data);
|
||||
break;
|
||||
case 2:
|
||||
pkt->set<uint16_t>(data);
|
||||
break;
|
||||
case 4:
|
||||
pkt->set<uint32_t>(data);
|
||||
break;
|
||||
default:
|
||||
panic("Uart read size too big?\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
Pl011::write(PacketPtr pkt)
|
||||
{
|
||||
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
DPRINTF(Uart, " write register %#x value %#x size=%d\n", daddr,
|
||||
pkt->get<uint8_t>(), pkt->getSize());
|
||||
|
||||
// use a temporary data since the uart registers are read/written with
|
||||
// different size operations
|
||||
//
|
||||
uint32_t data = 0;
|
||||
|
||||
switch(pkt->getSize()) {
|
||||
case 1:
|
||||
data = pkt->get<uint8_t>();
|
||||
break;
|
||||
case 2:
|
||||
data = pkt->get<uint16_t>();
|
||||
break;
|
||||
case 4:
|
||||
data = pkt->get<uint32_t>();
|
||||
break;
|
||||
default:
|
||||
panic("Uart write size too big?\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
switch (daddr) {
|
||||
case UART_DR:
|
||||
if ((data & 0xFF) == 0x04 && endOnEOT)
|
||||
exitSimLoop("UART received EOT", 0);
|
||||
|
||||
term->out(data & 0xFF);
|
||||
|
||||
//raw interrupt is set regardless of imsc.txim
|
||||
rawInt.txim = 1;
|
||||
if (imsc.txim) {
|
||||
DPRINTF(Uart, "TX int enabled, scheduling interruptt\n");
|
||||
if (!intEvent.scheduled())
|
||||
schedule(intEvent, curTick() + intDelay);
|
||||
}
|
||||
|
||||
break;
|
||||
case UART_CR:
|
||||
control = data;
|
||||
break;
|
||||
case UART_IBRD:
|
||||
ibrd = data;
|
||||
break;
|
||||
case UART_FBRD:
|
||||
fbrd = data;
|
||||
break;
|
||||
case UART_LCRH:
|
||||
lcrh = data;
|
||||
break;
|
||||
case UART_IFLS:
|
||||
ifls = data;
|
||||
break;
|
||||
case UART_IMSC:
|
||||
imsc = data;
|
||||
|
||||
if (imsc.rimim || imsc.ctsmim || imsc.dcdmim || imsc.dsrmim
|
||||
|| imsc.feim || imsc.peim || imsc.beim || imsc.oeim || imsc.rsvd)
|
||||
panic("Unknown interrupt enabled\n");
|
||||
|
||||
if (imsc.txim) {
|
||||
DPRINTF(Uart, "Writing to IMSC: TX int enabled, scheduling interruptt\n");
|
||||
rawInt.txim = 1;
|
||||
if (!intEvent.scheduled())
|
||||
schedule(intEvent, curTick() + intDelay);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case UART_ICR:
|
||||
DPRINTF(Uart, "Clearing interrupts 0x%x\n", data);
|
||||
rawInt = rawInt & ~data;
|
||||
maskInt = rawInt & imsc;
|
||||
|
||||
DPRINTF(Uart, " -- Masked interrupts 0x%x\n", maskInt);
|
||||
|
||||
if (!maskInt)
|
||||
gic->clearInt(intNum);
|
||||
|
||||
break;
|
||||
default:
|
||||
panic("Tried to write PL011 at offset %#x that doesn't exist\n", daddr);
|
||||
break;
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
Pl011::dataAvailable()
|
||||
{
|
||||
/*@todo ignore the fifo, just say we have data now
|
||||
* We might want to fix this, or we might not care */
|
||||
rawInt.rxim = 1;
|
||||
rawInt.rtim = 1;
|
||||
|
||||
DPRINTF(Uart, "Data available, scheduling interrupt\n");
|
||||
|
||||
if (!intEvent.scheduled())
|
||||
schedule(intEvent, curTick() + intDelay);
|
||||
}
|
||||
|
||||
void
|
||||
Pl011::generateInterrupt()
|
||||
{
|
||||
DPRINTF(Uart, "Generate Interrupt: imsc=0x%x rawInt=0x%x maskInt=0x%x\n",
|
||||
imsc, rawInt, maskInt);
|
||||
maskInt = imsc & rawInt;
|
||||
|
||||
if (maskInt.rxim || maskInt.rtim || maskInt.txim) {
|
||||
gic->sendInt(intNum);
|
||||
DPRINTF(Uart, " -- Generated\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Pl011::serialize(std::ostream &os)
|
||||
{
|
||||
DPRINTF(Checkpoint, "Serializing Arm PL011\n");
|
||||
SERIALIZE_SCALAR(control);
|
||||
SERIALIZE_SCALAR(fbrd);
|
||||
SERIALIZE_SCALAR(ibrd);
|
||||
SERIALIZE_SCALAR(lcrh);
|
||||
SERIALIZE_SCALAR(ifls);
|
||||
|
||||
uint16_t imsc_serial = imsc;
|
||||
SERIALIZE_SCALAR(imsc_serial);
|
||||
|
||||
uint16_t rawInt_serial = rawInt;
|
||||
SERIALIZE_SCALAR(rawInt_serial);
|
||||
|
||||
uint16_t maskInt_serial = maskInt;
|
||||
SERIALIZE_SCALAR(maskInt_serial);
|
||||
|
||||
SERIALIZE_SCALAR(endOnEOT);
|
||||
SERIALIZE_SCALAR(intDelay);
|
||||
}
|
||||
|
||||
void
|
||||
Pl011::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
DPRINTF(Checkpoint, "Unserializing Arm PL011\n");
|
||||
|
||||
UNSERIALIZE_SCALAR(control);
|
||||
UNSERIALIZE_SCALAR(fbrd);
|
||||
UNSERIALIZE_SCALAR(ibrd);
|
||||
UNSERIALIZE_SCALAR(lcrh);
|
||||
UNSERIALIZE_SCALAR(ifls);
|
||||
|
||||
uint16_t imsc_serial;
|
||||
UNSERIALIZE_SCALAR(imsc_serial);
|
||||
imsc = imsc_serial;
|
||||
|
||||
uint16_t rawInt_serial;
|
||||
UNSERIALIZE_SCALAR(rawInt_serial);
|
||||
rawInt = rawInt_serial;
|
||||
|
||||
uint16_t maskInt_serial;
|
||||
UNSERIALIZE_SCALAR(maskInt_serial);
|
||||
maskInt = maskInt_serial;
|
||||
|
||||
UNSERIALIZE_SCALAR(endOnEOT);
|
||||
UNSERIALIZE_SCALAR(intDelay);
|
||||
}
|
||||
|
||||
Pl011 *
|
||||
Pl011Params::create()
|
||||
{
|
||||
return new Pl011(this);
|
||||
}
|
||||
167
simulators/gem5/src/dev/arm/pl011.hh
Normal file
167
simulators/gem5/src/dev/arm/pl011.hh
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2005 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
|
||||
* Implementiation of a PL011 UART
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_PL011_H__
|
||||
#define __DEV_ARM_PL011_H__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "dev/uart.hh"
|
||||
#include "params/Pl011.hh"
|
||||
|
||||
class Gic;
|
||||
|
||||
class Pl011 : public Uart
|
||||
{
|
||||
protected:
|
||||
static const uint64_t AMBA_ID = ULL(0xb105f00d00341011);
|
||||
static const int UART_DR = 0x000;
|
||||
static const int UART_FR = 0x018;
|
||||
static const int UART_FR_CTS = 0x001;
|
||||
static const int UART_FR_TXFE = 0x080;
|
||||
static const int UART_FR_RXFE = 0x010;
|
||||
static const int UART_IBRD = 0x024;
|
||||
static const int UART_FBRD = 0x028;
|
||||
static const int UART_LCRH = 0x02C;
|
||||
static const int UART_CR = 0x030;
|
||||
static const int UART_IFLS = 0x034;
|
||||
static const int UART_IMSC = 0x038;
|
||||
static const int UART_RIS = 0x03C;
|
||||
static const int UART_MIS = 0x040;
|
||||
static const int UART_ICR = 0x044;
|
||||
|
||||
uint16_t control;
|
||||
|
||||
/** fractional baud rate divisor. Not used for anything but reporting
|
||||
* written value */
|
||||
uint16_t fbrd;
|
||||
|
||||
/** integer baud rate divisor. Not used for anything but reporting
|
||||
* written value */
|
||||
uint16_t ibrd;
|
||||
|
||||
/** Line control register. Not used for anything but reporting
|
||||
* written value */
|
||||
uint16_t lcrh;
|
||||
|
||||
/** interrupt fifo level register. Not used for anything but reporting
|
||||
* written value */
|
||||
uint16_t ifls;
|
||||
|
||||
BitUnion16(INTREG)
|
||||
Bitfield<0> rimim;
|
||||
Bitfield<1> ctsmim;
|
||||
Bitfield<2> dcdmim;
|
||||
Bitfield<3> dsrmim;
|
||||
Bitfield<4> rxim;
|
||||
Bitfield<5> txim;
|
||||
Bitfield<6> rtim;
|
||||
Bitfield<7> feim;
|
||||
Bitfield<8> peim;
|
||||
Bitfield<9> beim;
|
||||
Bitfield<10> oeim;
|
||||
Bitfield<15,11> rsvd;
|
||||
EndBitUnion(INTREG)
|
||||
|
||||
/** interrupt mask register. */
|
||||
INTREG imsc;
|
||||
|
||||
/** raw interrupt status register */
|
||||
INTREG rawInt;
|
||||
|
||||
/** Masked interrupt status register */
|
||||
INTREG maskInt;
|
||||
|
||||
/** Interrupt number to generate */
|
||||
int intNum;
|
||||
|
||||
/** Gic to use for interrupting */
|
||||
Gic *gic;
|
||||
|
||||
/** Should the simulation end on an EOT */
|
||||
bool endOnEOT;
|
||||
|
||||
/** Delay before interrupting */
|
||||
Tick intDelay;
|
||||
|
||||
/** Function to generate interrupt */
|
||||
void generateInterrupt();
|
||||
|
||||
/** Wrapper to create an event out of the thing */
|
||||
EventWrapper<Pl011, &Pl011::generateInterrupt> intEvent;
|
||||
|
||||
public:
|
||||
typedef Pl011Params Params;
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
Pl011(const Params *p);
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* Inform the uart that there is data available.
|
||||
*/
|
||||
virtual void dataAvailable();
|
||||
|
||||
|
||||
/**
|
||||
* Return if we have an interrupt pending
|
||||
* @return interrupt status
|
||||
* @todo fix me when implementation improves
|
||||
*/
|
||||
virtual bool intStatus() { return false; }
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
};
|
||||
|
||||
#endif //__DEV_ARM_PL011_H__
|
||||
757
simulators/gem5/src/dev/arm/pl111.cc
Normal file
757
simulators/gem5/src/dev/arm/pl111.cc
Normal file
@ -0,0 +1,757 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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: William Wang
|
||||
* Ali Saidi
|
||||
*/
|
||||
|
||||
#include "base/vnc/vncserver.hh"
|
||||
#include "base/bitmap.hh"
|
||||
#include "base/output.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/PL111.hh"
|
||||
#include "debug/Uart.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "dev/arm/gic.hh"
|
||||
#include "dev/arm/pl111.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
// clang complains about std::set being overloaded with Packet::set if
|
||||
// we open up the entire namespace std
|
||||
using std::vector;
|
||||
|
||||
using namespace AmbaDev;
|
||||
|
||||
// initialize clcd registers
|
||||
Pl111::Pl111(const Params *p)
|
||||
: AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0),
|
||||
lcdTiming3(0), lcdUpbase(0), lcdLpbase(0), lcdControl(0), lcdImsc(0),
|
||||
lcdRis(0), lcdMis(0),
|
||||
clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
|
||||
clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
|
||||
clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0), clock(p->clock),
|
||||
vncserver(p->vnc), bmp(NULL), width(LcdMaxWidth), height(LcdMaxHeight),
|
||||
bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
|
||||
waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
|
||||
dmaDoneEvent(maxOutstandingDma, this), intEvent(this)
|
||||
{
|
||||
pioSize = 0xFFFF;
|
||||
|
||||
pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true);
|
||||
|
||||
const int buffer_size = LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t);
|
||||
dmaBuffer = new uint8_t[buffer_size];
|
||||
|
||||
memset(lcdPalette, 0, sizeof(lcdPalette));
|
||||
memset(cursorImage, 0, sizeof(cursorImage));
|
||||
memset(dmaBuffer, 0, buffer_size);
|
||||
|
||||
if (vncserver)
|
||||
vncserver->setFramebufferAddr(dmaBuffer);
|
||||
}
|
||||
|
||||
// read registers and frame buffer
|
||||
Tick
|
||||
Pl111::read(PacketPtr pkt)
|
||||
{
|
||||
// use a temporary data since the LCD registers are read/written with
|
||||
// different size operations
|
||||
|
||||
uint32_t data = 0;
|
||||
|
||||
assert(pkt->getAddr() >= pioAddr &&
|
||||
pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
|
||||
DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize());
|
||||
|
||||
switch (daddr) {
|
||||
case LcdTiming0:
|
||||
data = lcdTiming0;
|
||||
break;
|
||||
case LcdTiming1:
|
||||
data = lcdTiming1;
|
||||
break;
|
||||
case LcdTiming2:
|
||||
data = lcdTiming2;
|
||||
break;
|
||||
case LcdTiming3:
|
||||
data = lcdTiming3;
|
||||
break;
|
||||
case LcdUpBase:
|
||||
data = lcdUpbase;
|
||||
break;
|
||||
case LcdLpBase:
|
||||
data = lcdLpbase;
|
||||
break;
|
||||
case LcdControl:
|
||||
data = lcdControl;
|
||||
break;
|
||||
case LcdImsc:
|
||||
data = lcdImsc;
|
||||
break;
|
||||
case LcdRis:
|
||||
data = lcdRis;
|
||||
break;
|
||||
case LcdMis:
|
||||
data = lcdMis;
|
||||
break;
|
||||
case LcdIcr:
|
||||
panic("LCD register at offset %#x is Write-Only\n", daddr);
|
||||
break;
|
||||
case LcdUpCurr:
|
||||
data = curAddr;
|
||||
break;
|
||||
case LcdLpCurr:
|
||||
data = curAddr;
|
||||
break;
|
||||
case ClcdCrsrCtrl:
|
||||
data = clcdCrsrCtrl;
|
||||
break;
|
||||
case ClcdCrsrConfig:
|
||||
data = clcdCrsrConfig;
|
||||
break;
|
||||
case ClcdCrsrPalette0:
|
||||
data = clcdCrsrPalette0;
|
||||
break;
|
||||
case ClcdCrsrPalette1:
|
||||
data = clcdCrsrPalette1;
|
||||
break;
|
||||
case ClcdCrsrXY:
|
||||
data = clcdCrsrXY;
|
||||
break;
|
||||
case ClcdCrsrClip:
|
||||
data = clcdCrsrClip;
|
||||
break;
|
||||
case ClcdCrsrImsc:
|
||||
data = clcdCrsrImsc;
|
||||
break;
|
||||
case ClcdCrsrIcr:
|
||||
panic("CLCD register at offset %#x is Write-Only\n", daddr);
|
||||
break;
|
||||
case ClcdCrsrRis:
|
||||
data = clcdCrsrRis;
|
||||
break;
|
||||
case ClcdCrsrMis:
|
||||
data = clcdCrsrMis;
|
||||
break;
|
||||
default:
|
||||
if (AmbaDev::readId(pkt, AMBA_ID, pioAddr)) {
|
||||
// Hack for variable size accesses
|
||||
data = pkt->get<uint32_t>();
|
||||
break;
|
||||
} else if (daddr >= CrsrImage && daddr <= 0xBFC) {
|
||||
// CURSOR IMAGE
|
||||
int index;
|
||||
index = (daddr - CrsrImage) >> 2;
|
||||
data= cursorImage[index];
|
||||
break;
|
||||
} else if (daddr >= LcdPalette && daddr <= 0x3FC) {
|
||||
// LCD Palette
|
||||
int index;
|
||||
index = (daddr - LcdPalette) >> 2;
|
||||
data = lcdPalette[index];
|
||||
break;
|
||||
} else {
|
||||
panic("Tried to read CLCD register at offset %#x that \
|
||||
doesn't exist\n", daddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(pkt->getSize()) {
|
||||
case 1:
|
||||
pkt->set<uint8_t>(data);
|
||||
break;
|
||||
case 2:
|
||||
pkt->set<uint16_t>(data);
|
||||
break;
|
||||
case 4:
|
||||
pkt->set<uint32_t>(data);
|
||||
break;
|
||||
default:
|
||||
panic("CLCD controller read size too big?\n");
|
||||
break;
|
||||
}
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
// write registers and frame buffer
|
||||
Tick
|
||||
Pl111::write(PacketPtr pkt)
|
||||
{
|
||||
// use a temporary data since the LCD registers are read/written with
|
||||
// different size operations
|
||||
//
|
||||
uint32_t data = 0;
|
||||
|
||||
switch(pkt->getSize()) {
|
||||
case 1:
|
||||
data = pkt->get<uint8_t>();
|
||||
break;
|
||||
case 2:
|
||||
data = pkt->get<uint16_t>();
|
||||
break;
|
||||
case 4:
|
||||
data = pkt->get<uint32_t>();
|
||||
break;
|
||||
default:
|
||||
panic("PL111 CLCD controller write size too big?\n");
|
||||
break;
|
||||
}
|
||||
|
||||
assert(pkt->getAddr() >= pioAddr &&
|
||||
pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr,
|
||||
pkt->get<uint8_t>(), pkt->getSize());
|
||||
|
||||
switch (daddr) {
|
||||
case LcdTiming0:
|
||||
lcdTiming0 = data;
|
||||
// width = 16 * (PPL+1)
|
||||
width = (lcdTiming0.ppl + 1) << 4;
|
||||
break;
|
||||
case LcdTiming1:
|
||||
lcdTiming1 = data;
|
||||
// height = LPP + 1
|
||||
height = (lcdTiming1.lpp) + 1;
|
||||
break;
|
||||
case LcdTiming2:
|
||||
lcdTiming2 = data;
|
||||
break;
|
||||
case LcdTiming3:
|
||||
lcdTiming3 = data;
|
||||
break;
|
||||
case LcdUpBase:
|
||||
lcdUpbase = data;
|
||||
DPRINTF(PL111, "####### Upper panel base set to: %#x #######\n", lcdUpbase);
|
||||
break;
|
||||
case LcdLpBase:
|
||||
warn_once("LCD dual screen mode not supported\n");
|
||||
lcdLpbase = data;
|
||||
DPRINTF(PL111, "###### Lower panel base set to: %#x #######\n", lcdLpbase);
|
||||
break;
|
||||
case LcdControl:
|
||||
int old_lcdpwr;
|
||||
old_lcdpwr = lcdControl.lcdpwr;
|
||||
lcdControl = data;
|
||||
|
||||
DPRINTF(PL111, "LCD power is:%d\n", lcdControl.lcdpwr);
|
||||
|
||||
// LCD power enable
|
||||
if (lcdControl.lcdpwr && !old_lcdpwr) {
|
||||
updateVideoParams();
|
||||
DPRINTF(PL111, " lcd size: height %d width %d\n", height, width);
|
||||
waterMark = lcdControl.watermark ? 8 : 4;
|
||||
startDma();
|
||||
}
|
||||
break;
|
||||
case LcdImsc:
|
||||
lcdImsc = data;
|
||||
if (lcdImsc.vcomp)
|
||||
panic("Interrupting on vcomp not supported\n");
|
||||
|
||||
lcdMis = lcdImsc & lcdRis;
|
||||
|
||||
if (!lcdMis)
|
||||
gic->clearInt(intNum);
|
||||
|
||||
break;
|
||||
case LcdRis:
|
||||
panic("LCD register at offset %#x is Read-Only\n", daddr);
|
||||
break;
|
||||
case LcdMis:
|
||||
panic("LCD register at offset %#x is Read-Only\n", daddr);
|
||||
break;
|
||||
case LcdIcr:
|
||||
lcdRis = lcdRis & ~data;
|
||||
lcdMis = lcdImsc & lcdRis;
|
||||
|
||||
if (!lcdMis)
|
||||
gic->clearInt(intNum);
|
||||
|
||||
break;
|
||||
case LcdUpCurr:
|
||||
panic("LCD register at offset %#x is Read-Only\n", daddr);
|
||||
break;
|
||||
case LcdLpCurr:
|
||||
panic("LCD register at offset %#x is Read-Only\n", daddr);
|
||||
break;
|
||||
case ClcdCrsrCtrl:
|
||||
clcdCrsrCtrl = data;
|
||||
break;
|
||||
case ClcdCrsrConfig:
|
||||
clcdCrsrConfig = data;
|
||||
break;
|
||||
case ClcdCrsrPalette0:
|
||||
clcdCrsrPalette0 = data;
|
||||
break;
|
||||
case ClcdCrsrPalette1:
|
||||
clcdCrsrPalette1 = data;
|
||||
break;
|
||||
case ClcdCrsrXY:
|
||||
clcdCrsrXY = data;
|
||||
break;
|
||||
case ClcdCrsrClip:
|
||||
clcdCrsrClip = data;
|
||||
break;
|
||||
case ClcdCrsrImsc:
|
||||
clcdCrsrImsc = data;
|
||||
break;
|
||||
case ClcdCrsrIcr:
|
||||
clcdCrsrIcr = data;
|
||||
break;
|
||||
case ClcdCrsrRis:
|
||||
panic("CLCD register at offset %#x is Read-Only\n", daddr);
|
||||
break;
|
||||
case ClcdCrsrMis:
|
||||
panic("CLCD register at offset %#x is Read-Only\n", daddr);
|
||||
break;
|
||||
default:
|
||||
if (daddr >= CrsrImage && daddr <= 0xBFC) {
|
||||
// CURSOR IMAGE
|
||||
int index;
|
||||
index = (daddr - CrsrImage) >> 2;
|
||||
cursorImage[index] = data;
|
||||
break;
|
||||
} else if (daddr >= LcdPalette && daddr <= 0x3FC) {
|
||||
// LCD Palette
|
||||
int index;
|
||||
index = (daddr - LcdPalette) >> 2;
|
||||
lcdPalette[index] = data;
|
||||
break;
|
||||
} else {
|
||||
panic("Tried to write PL111 register at offset %#x that \
|
||||
doesn't exist\n", daddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::updateVideoParams()
|
||||
{
|
||||
if (lcdControl.lcdbpp == bpp24) {
|
||||
bytesPerPixel = 4;
|
||||
} else if (lcdControl.lcdbpp == bpp16m565) {
|
||||
bytesPerPixel = 2;
|
||||
}
|
||||
|
||||
if (vncserver) {
|
||||
if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
|
||||
vncserver->setFrameBufferParams(VideoConvert::bgr8888, width,
|
||||
height);
|
||||
else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
|
||||
vncserver->setFrameBufferParams(VideoConvert::rgb8888, width,
|
||||
height);
|
||||
else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
|
||||
vncserver->setFrameBufferParams(VideoConvert::bgr565, width,
|
||||
height);
|
||||
else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
|
||||
vncserver->setFrameBufferParams(VideoConvert::rgb565, width,
|
||||
height);
|
||||
else
|
||||
panic("Unimplemented video mode\n");
|
||||
}
|
||||
|
||||
if (bmp)
|
||||
delete bmp;
|
||||
|
||||
if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
|
||||
bmp = new Bitmap(VideoConvert::bgr8888, width, height, dmaBuffer);
|
||||
else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
|
||||
bmp = new Bitmap(VideoConvert::rgb8888, width, height, dmaBuffer);
|
||||
else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
|
||||
bmp = new Bitmap(VideoConvert::bgr565, width, height, dmaBuffer);
|
||||
else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
|
||||
bmp = new Bitmap(VideoConvert::rgb565, width, height, dmaBuffer);
|
||||
else
|
||||
panic("Unimplemented video mode\n");
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::startDma()
|
||||
{
|
||||
if (dmaPendingNum != 0 || readEvent.scheduled())
|
||||
return;
|
||||
readFramebuffer();
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::readFramebuffer()
|
||||
{
|
||||
// initialization for dma read from frame buffer to dma buffer
|
||||
uint32_t length = height * width;
|
||||
if (startAddr != lcdUpbase)
|
||||
startAddr = lcdUpbase;
|
||||
|
||||
// Updating base address, interrupt if we're supposed to
|
||||
lcdRis.baseaddr = 1;
|
||||
if (!intEvent.scheduled())
|
||||
schedule(intEvent, nextCycle());
|
||||
|
||||
curAddr = 0;
|
||||
startTime = curTick();
|
||||
|
||||
maxAddr = static_cast<Addr>(length * bytesPerPixel);
|
||||
|
||||
DPRINTF(PL111, " lcd frame buffer size of %d bytes \n", maxAddr);
|
||||
|
||||
dmaPendingNum = 0;
|
||||
|
||||
fillFifo();
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::fillFifo()
|
||||
{
|
||||
while ((dmaPendingNum < maxOutstandingDma) && (maxAddr >= curAddr + dmaSize )) {
|
||||
// concurrent dma reads need different dma done events
|
||||
// due to assertion in scheduling state
|
||||
++dmaPendingNum;
|
||||
|
||||
assert(!dmaDoneEvent[dmaPendingNum-1].scheduled());
|
||||
|
||||
// We use a uncachable request here because the requests from the CPU
|
||||
// will be uncacheable as well. If we have uncacheable and cacheable
|
||||
// requests in the memory system for the same address it won't be
|
||||
// pleased
|
||||
dmaPort.dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize,
|
||||
&dmaDoneEvent[dmaPendingNum-1], curAddr + dmaBuffer,
|
||||
0, Request::UNCACHEABLE);
|
||||
curAddr += dmaSize;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::dmaDone()
|
||||
{
|
||||
Tick maxFrameTime = lcdTiming2.cpl * height * clock;
|
||||
|
||||
--dmaPendingNum;
|
||||
|
||||
if (maxAddr == curAddr && !dmaPendingNum) {
|
||||
if ((curTick() - startTime) > maxFrameTime) {
|
||||
warn("CLCD controller buffer underrun, took %d cycles when should"
|
||||
" have taken %d\n", curTick() - startTime, maxFrameTime);
|
||||
lcdRis.underflow = 1;
|
||||
if (!intEvent.scheduled())
|
||||
schedule(intEvent, nextCycle());
|
||||
}
|
||||
|
||||
assert(!readEvent.scheduled());
|
||||
if (vncserver)
|
||||
vncserver->setDirty();
|
||||
|
||||
DPRINTF(PL111, "-- write out frame buffer into bmp\n");
|
||||
|
||||
assert(bmp);
|
||||
pic->seekp(0);
|
||||
bmp->write(pic);
|
||||
|
||||
DPRINTF(PL111, "-- schedule next dma read event at %d tick \n",
|
||||
maxFrameTime + curTick());
|
||||
|
||||
if (lcdControl.lcden)
|
||||
schedule(readEvent, nextCycle(startTime + maxFrameTime));
|
||||
}
|
||||
|
||||
if (dmaPendingNum > (maxOutstandingDma - waterMark))
|
||||
return;
|
||||
|
||||
if (!fillFifoEvent.scheduled())
|
||||
schedule(fillFifoEvent, nextCycle());
|
||||
}
|
||||
|
||||
|
||||
Tick
|
||||
Pl111::nextCycle()
|
||||
{
|
||||
Tick nextTick = curTick() + clock - 1;
|
||||
nextTick -= nextTick%clock;
|
||||
return nextTick;
|
||||
}
|
||||
|
||||
Tick
|
||||
Pl111::nextCycle(Tick beginTick)
|
||||
{
|
||||
Tick nextTick = beginTick;
|
||||
if (nextTick%clock!=0)
|
||||
nextTick = nextTick - (nextTick%clock) + clock;
|
||||
|
||||
assert(nextTick >= curTick());
|
||||
return nextTick;
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::serialize(std::ostream &os)
|
||||
{
|
||||
DPRINTF(PL111, "Serializing ARM PL111\n");
|
||||
|
||||
uint32_t lcdTiming0_serial = lcdTiming0;
|
||||
SERIALIZE_SCALAR(lcdTiming0_serial);
|
||||
|
||||
uint32_t lcdTiming1_serial = lcdTiming1;
|
||||
SERIALIZE_SCALAR(lcdTiming1_serial);
|
||||
|
||||
uint32_t lcdTiming2_serial = lcdTiming2;
|
||||
SERIALIZE_SCALAR(lcdTiming2_serial);
|
||||
|
||||
uint32_t lcdTiming3_serial = lcdTiming3;
|
||||
SERIALIZE_SCALAR(lcdTiming3_serial);
|
||||
|
||||
SERIALIZE_SCALAR(lcdUpbase);
|
||||
SERIALIZE_SCALAR(lcdLpbase);
|
||||
|
||||
uint32_t lcdControl_serial = lcdControl;
|
||||
SERIALIZE_SCALAR(lcdControl_serial);
|
||||
|
||||
uint8_t lcdImsc_serial = lcdImsc;
|
||||
SERIALIZE_SCALAR(lcdImsc_serial);
|
||||
|
||||
uint8_t lcdRis_serial = lcdRis;
|
||||
SERIALIZE_SCALAR(lcdRis_serial);
|
||||
|
||||
uint8_t lcdMis_serial = lcdMis;
|
||||
SERIALIZE_SCALAR(lcdMis_serial);
|
||||
|
||||
SERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
|
||||
SERIALIZE_ARRAY(cursorImage, CrsrImageSize);
|
||||
|
||||
SERIALIZE_SCALAR(clcdCrsrCtrl);
|
||||
SERIALIZE_SCALAR(clcdCrsrConfig);
|
||||
SERIALIZE_SCALAR(clcdCrsrPalette0);
|
||||
SERIALIZE_SCALAR(clcdCrsrPalette1);
|
||||
SERIALIZE_SCALAR(clcdCrsrXY);
|
||||
SERIALIZE_SCALAR(clcdCrsrClip);
|
||||
|
||||
uint8_t clcdCrsrImsc_serial = clcdCrsrImsc;
|
||||
SERIALIZE_SCALAR(clcdCrsrImsc_serial);
|
||||
|
||||
uint8_t clcdCrsrIcr_serial = clcdCrsrIcr;
|
||||
SERIALIZE_SCALAR(clcdCrsrIcr_serial);
|
||||
|
||||
uint8_t clcdCrsrRis_serial = clcdCrsrRis;
|
||||
SERIALIZE_SCALAR(clcdCrsrRis_serial);
|
||||
|
||||
uint8_t clcdCrsrMis_serial = clcdCrsrMis;
|
||||
SERIALIZE_SCALAR(clcdCrsrMis_serial);
|
||||
|
||||
SERIALIZE_SCALAR(clock);
|
||||
SERIALIZE_SCALAR(height);
|
||||
SERIALIZE_SCALAR(width);
|
||||
SERIALIZE_SCALAR(bytesPerPixel);
|
||||
|
||||
SERIALIZE_ARRAY(dmaBuffer, height * width);
|
||||
SERIALIZE_SCALAR(startTime);
|
||||
SERIALIZE_SCALAR(startAddr);
|
||||
SERIALIZE_SCALAR(maxAddr);
|
||||
SERIALIZE_SCALAR(curAddr);
|
||||
SERIALIZE_SCALAR(waterMark);
|
||||
SERIALIZE_SCALAR(dmaPendingNum);
|
||||
|
||||
Tick int_event_time = 0;
|
||||
Tick read_event_time = 0;
|
||||
Tick fill_fifo_event_time = 0;
|
||||
|
||||
if (readEvent.scheduled())
|
||||
read_event_time = readEvent.when();
|
||||
if (fillFifoEvent.scheduled())
|
||||
fill_fifo_event_time = fillFifoEvent.when();
|
||||
if (intEvent.scheduled())
|
||||
int_event_time = intEvent.when();
|
||||
|
||||
SERIALIZE_SCALAR(read_event_time);
|
||||
SERIALIZE_SCALAR(fill_fifo_event_time);
|
||||
SERIALIZE_SCALAR(int_event_time);
|
||||
|
||||
vector<Tick> dma_done_event_tick;
|
||||
dma_done_event_tick.resize(maxOutstandingDma);
|
||||
for (int x = 0; x < maxOutstandingDma; x++) {
|
||||
dma_done_event_tick[x] = dmaDoneEvent[x].scheduled() ?
|
||||
dmaDoneEvent[x].when() : 0;
|
||||
}
|
||||
arrayParamOut(os, "dma_done_event_tick", dma_done_event_tick);
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
DPRINTF(PL111, "Unserializing ARM PL111\n");
|
||||
|
||||
uint32_t lcdTiming0_serial;
|
||||
UNSERIALIZE_SCALAR(lcdTiming0_serial);
|
||||
lcdTiming0 = lcdTiming0_serial;
|
||||
|
||||
uint32_t lcdTiming1_serial;
|
||||
UNSERIALIZE_SCALAR(lcdTiming1_serial);
|
||||
lcdTiming1 = lcdTiming1_serial;
|
||||
|
||||
uint32_t lcdTiming2_serial;
|
||||
UNSERIALIZE_SCALAR(lcdTiming2_serial);
|
||||
lcdTiming2 = lcdTiming2_serial;
|
||||
|
||||
uint32_t lcdTiming3_serial;
|
||||
UNSERIALIZE_SCALAR(lcdTiming3_serial);
|
||||
lcdTiming3 = lcdTiming3_serial;
|
||||
|
||||
UNSERIALIZE_SCALAR(lcdUpbase);
|
||||
UNSERIALIZE_SCALAR(lcdLpbase);
|
||||
|
||||
uint32_t lcdControl_serial;
|
||||
UNSERIALIZE_SCALAR(lcdControl_serial);
|
||||
lcdControl = lcdControl_serial;
|
||||
|
||||
uint8_t lcdImsc_serial;
|
||||
UNSERIALIZE_SCALAR(lcdImsc_serial);
|
||||
lcdImsc = lcdImsc_serial;
|
||||
|
||||
uint8_t lcdRis_serial;
|
||||
UNSERIALIZE_SCALAR(lcdRis_serial);
|
||||
lcdRis = lcdRis_serial;
|
||||
|
||||
uint8_t lcdMis_serial;
|
||||
UNSERIALIZE_SCALAR(lcdMis_serial);
|
||||
lcdMis = lcdMis_serial;
|
||||
|
||||
UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
|
||||
UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize);
|
||||
|
||||
UNSERIALIZE_SCALAR(clcdCrsrCtrl);
|
||||
UNSERIALIZE_SCALAR(clcdCrsrConfig);
|
||||
UNSERIALIZE_SCALAR(clcdCrsrPalette0);
|
||||
UNSERIALIZE_SCALAR(clcdCrsrPalette1);
|
||||
UNSERIALIZE_SCALAR(clcdCrsrXY);
|
||||
UNSERIALIZE_SCALAR(clcdCrsrClip);
|
||||
|
||||
uint8_t clcdCrsrImsc_serial;
|
||||
UNSERIALIZE_SCALAR(clcdCrsrImsc_serial);
|
||||
clcdCrsrImsc = clcdCrsrImsc_serial;
|
||||
|
||||
uint8_t clcdCrsrIcr_serial;
|
||||
UNSERIALIZE_SCALAR(clcdCrsrIcr_serial);
|
||||
clcdCrsrIcr = clcdCrsrIcr_serial;
|
||||
|
||||
uint8_t clcdCrsrRis_serial;
|
||||
UNSERIALIZE_SCALAR(clcdCrsrRis_serial);
|
||||
clcdCrsrRis = clcdCrsrRis_serial;
|
||||
|
||||
uint8_t clcdCrsrMis_serial;
|
||||
UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
|
||||
clcdCrsrMis = clcdCrsrMis_serial;
|
||||
|
||||
UNSERIALIZE_SCALAR(clock);
|
||||
UNSERIALIZE_SCALAR(height);
|
||||
UNSERIALIZE_SCALAR(width);
|
||||
UNSERIALIZE_SCALAR(bytesPerPixel);
|
||||
|
||||
UNSERIALIZE_ARRAY(dmaBuffer, height * width);
|
||||
UNSERIALIZE_SCALAR(startTime);
|
||||
UNSERIALIZE_SCALAR(startAddr);
|
||||
UNSERIALIZE_SCALAR(maxAddr);
|
||||
UNSERIALIZE_SCALAR(curAddr);
|
||||
UNSERIALIZE_SCALAR(waterMark);
|
||||
UNSERIALIZE_SCALAR(dmaPendingNum);
|
||||
|
||||
Tick int_event_time = 0;
|
||||
Tick read_event_time = 0;
|
||||
Tick fill_fifo_event_time = 0;
|
||||
|
||||
UNSERIALIZE_SCALAR(read_event_time);
|
||||
UNSERIALIZE_SCALAR(fill_fifo_event_time);
|
||||
UNSERIALIZE_SCALAR(int_event_time);
|
||||
|
||||
if (int_event_time)
|
||||
schedule(intEvent, int_event_time);
|
||||
if (read_event_time)
|
||||
schedule(readEvent, read_event_time);
|
||||
if (fill_fifo_event_time)
|
||||
schedule(fillFifoEvent, fill_fifo_event_time);
|
||||
|
||||
vector<Tick> dma_done_event_tick;
|
||||
dma_done_event_tick.resize(maxOutstandingDma);
|
||||
arrayParamIn(cp, section, "dma_done_event_tick", dma_done_event_tick);
|
||||
for (int x = 0; x < maxOutstandingDma; x++) {
|
||||
if (dma_done_event_tick[x])
|
||||
schedule(dmaDoneEvent[x], dma_done_event_tick[x]);
|
||||
}
|
||||
|
||||
if (lcdControl.lcdpwr) {
|
||||
updateVideoParams();
|
||||
if (vncserver)
|
||||
vncserver->setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::generateInterrupt()
|
||||
{
|
||||
DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
|
||||
(uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis);
|
||||
lcdMis = lcdImsc & lcdRis;
|
||||
|
||||
if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) {
|
||||
gic->sendInt(intNum);
|
||||
DPRINTF(PL111, " -- Generated\n");
|
||||
}
|
||||
}
|
||||
|
||||
AddrRangeList
|
||||
Pl111::getAddrRanges()
|
||||
{
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(pioAddr, pioSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
Pl111 *
|
||||
Pl111Params::create()
|
||||
{
|
||||
return new Pl111(this);
|
||||
}
|
||||
|
||||
|
||||
334
simulators/gem5/src/dev/arm/pl111.hh
Normal file
334
simulators/gem5/src/dev/arm/pl111.hh
Normal file
@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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: William Wang
|
||||
* Ali Saidi
|
||||
*/
|
||||
|
||||
|
||||
/** @file
|
||||
* Implementiation of a PL111 CLCD controller
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_PL111_HH__
|
||||
#define __DEV_ARM_PL111_HH__
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "params/Pl111.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
class Gic;
|
||||
class VncServer;
|
||||
class Bitmap;
|
||||
|
||||
class Pl111: public AmbaDmaDevice
|
||||
{
|
||||
protected:
|
||||
static const uint64_t AMBA_ID = ULL(0xb105f00d00141111);
|
||||
/** ARM PL111 register map*/
|
||||
static const int LcdTiming0 = 0x000;
|
||||
static const int LcdTiming1 = 0x004;
|
||||
static const int LcdTiming2 = 0x008;
|
||||
static const int LcdTiming3 = 0x00C;
|
||||
static const int LcdUpBase = 0x010;
|
||||
static const int LcdLpBase = 0x014;
|
||||
static const int LcdControl = 0x018;
|
||||
static const int LcdImsc = 0x01C;
|
||||
static const int LcdRis = 0x020;
|
||||
static const int LcdMis = 0x024;
|
||||
static const int LcdIcr = 0x028;
|
||||
static const int LcdUpCurr = 0x02C;
|
||||
static const int LcdLpCurr = 0x030;
|
||||
static const int LcdPalette = 0x200;
|
||||
static const int CrsrImage = 0x800;
|
||||
static const int ClcdCrsrCtrl = 0xC00;
|
||||
static const int ClcdCrsrConfig = 0xC04;
|
||||
static const int ClcdCrsrPalette0 = 0xC08;
|
||||
static const int ClcdCrsrPalette1 = 0xC0C;
|
||||
static const int ClcdCrsrXY = 0xC10;
|
||||
static const int ClcdCrsrClip = 0xC14;
|
||||
static const int ClcdCrsrImsc = 0xC20;
|
||||
static const int ClcdCrsrIcr = 0xC24;
|
||||
static const int ClcdCrsrRis = 0xC28;
|
||||
static const int ClcdCrsrMis = 0xC2C;
|
||||
|
||||
static const int LcdPaletteSize = 128;
|
||||
static const int CrsrImageSize = 256;
|
||||
|
||||
static const int LcdMaxWidth = 1024; // pixels per line
|
||||
static const int LcdMaxHeight = 768; // lines per panel
|
||||
|
||||
static const int dmaSize = 8; // 64 bits
|
||||
static const int maxOutstandingDma = 16; // 16 deep FIFO of 64 bits
|
||||
|
||||
enum LcdMode {
|
||||
bpp1 = 0,
|
||||
bpp2,
|
||||
bpp4,
|
||||
bpp8,
|
||||
bpp16,
|
||||
bpp24,
|
||||
bpp16m565,
|
||||
bpp12
|
||||
};
|
||||
|
||||
BitUnion8(InterruptReg)
|
||||
Bitfield<1> underflow;
|
||||
Bitfield<2> baseaddr;
|
||||
Bitfield<3> vcomp;
|
||||
Bitfield<4> ahbmaster;
|
||||
EndBitUnion(InterruptReg)
|
||||
|
||||
BitUnion32(TimingReg0)
|
||||
Bitfield<7,2> ppl;
|
||||
Bitfield<15,8> hsw;
|
||||
Bitfield<23,16> hfp;
|
||||
Bitfield<31,24> hbp;
|
||||
EndBitUnion(TimingReg0)
|
||||
|
||||
BitUnion32(TimingReg1)
|
||||
Bitfield<9,0> lpp;
|
||||
Bitfield<15,10> vsw;
|
||||
Bitfield<23,16> vfp;
|
||||
Bitfield<31,24> vbp;
|
||||
EndBitUnion(TimingReg1)
|
||||
|
||||
BitUnion32(TimingReg2)
|
||||
Bitfield<4,0> pcdlo;
|
||||
Bitfield<5> clksel;
|
||||
Bitfield<10,6> acb;
|
||||
Bitfield<11> avs;
|
||||
Bitfield<12> ihs;
|
||||
Bitfield<13> ipc;
|
||||
Bitfield<14> ioe;
|
||||
Bitfield<25,16> cpl;
|
||||
Bitfield<26> bcd;
|
||||
Bitfield<31,27> pcdhi;
|
||||
EndBitUnion(TimingReg2)
|
||||
|
||||
BitUnion32(TimingReg3)
|
||||
Bitfield<6,0> led;
|
||||
Bitfield<16> lee;
|
||||
EndBitUnion(TimingReg3)
|
||||
|
||||
BitUnion32(ControlReg)
|
||||
Bitfield<0> lcden;
|
||||
Bitfield<3,1> lcdbpp;
|
||||
Bitfield<4> lcdbw;
|
||||
Bitfield<5> lcdtft;
|
||||
Bitfield<6> lcdmono8;
|
||||
Bitfield<7> lcddual;
|
||||
Bitfield<8> bgr;
|
||||
Bitfield<9> bebo;
|
||||
Bitfield<10> bepo;
|
||||
Bitfield<11> lcdpwr;
|
||||
Bitfield<13,12> lcdvcomp;
|
||||
Bitfield<16> watermark;
|
||||
EndBitUnion(ControlReg)
|
||||
|
||||
/** Horizontal axis panel control register */
|
||||
TimingReg0 lcdTiming0;
|
||||
|
||||
/** Vertical axis panel control register */
|
||||
TimingReg1 lcdTiming1;
|
||||
|
||||
/** Clock and signal polarity control register */
|
||||
TimingReg2 lcdTiming2;
|
||||
|
||||
/** Line end control register */
|
||||
TimingReg3 lcdTiming3;
|
||||
|
||||
/** Upper panel frame base address register */
|
||||
int lcdUpbase;
|
||||
|
||||
/** Lower panel frame base address register */
|
||||
int lcdLpbase;
|
||||
|
||||
/** Control register */
|
||||
ControlReg lcdControl;
|
||||
|
||||
/** Interrupt mask set/clear register */
|
||||
InterruptReg lcdImsc;
|
||||
|
||||
/** Raw interrupt status register - const */
|
||||
InterruptReg lcdRis;
|
||||
|
||||
/** Masked interrupt status register */
|
||||
InterruptReg lcdMis;
|
||||
|
||||
/** 256x16-bit color palette registers
|
||||
* 256 palette entries organized as 128 locations of two entries per word */
|
||||
int lcdPalette[LcdPaletteSize];
|
||||
|
||||
/** Cursor image RAM register
|
||||
* 256-word wide values defining images overlaid by the hw cursor mechanism */
|
||||
int cursorImage[CrsrImageSize];
|
||||
|
||||
/** Cursor control register */
|
||||
int clcdCrsrCtrl;
|
||||
|
||||
/** Cursor configuration register */
|
||||
int clcdCrsrConfig;
|
||||
|
||||
/** Cursor palette registers */
|
||||
int clcdCrsrPalette0;
|
||||
int clcdCrsrPalette1;
|
||||
|
||||
/** Cursor XY position register */
|
||||
int clcdCrsrXY;
|
||||
|
||||
/** Cursor clip position register */
|
||||
int clcdCrsrClip;
|
||||
|
||||
/** Cursor interrupt mask set/clear register */
|
||||
InterruptReg clcdCrsrImsc;
|
||||
|
||||
/** Cursor interrupt clear register */
|
||||
InterruptReg clcdCrsrIcr;
|
||||
|
||||
/** Cursor raw interrupt status register - const */
|
||||
InterruptReg clcdCrsrRis;
|
||||
|
||||
/** Cursor masked interrupt status register - const */
|
||||
InterruptReg clcdCrsrMis;
|
||||
|
||||
/** Clock speed */
|
||||
Tick clock;
|
||||
|
||||
/** VNC server */
|
||||
VncServer *vncserver;
|
||||
|
||||
/** Helper to write out bitmaps */
|
||||
Bitmap *bmp;
|
||||
|
||||
/** Picture of what the current frame buffer looks like */
|
||||
std::ostream *pic;
|
||||
|
||||
/** Frame buffer width - pixels per line */
|
||||
uint16_t width;
|
||||
|
||||
/** Frame buffer height - lines per panel */
|
||||
uint16_t height;
|
||||
|
||||
/** Bytes per pixel */
|
||||
uint8_t bytesPerPixel;
|
||||
|
||||
/** CLCDC supports up to 1024x768 */
|
||||
uint8_t *dmaBuffer;
|
||||
|
||||
/** Start time for frame buffer dma read */
|
||||
Tick startTime;
|
||||
|
||||
/** Frame buffer base address */
|
||||
Addr startAddr;
|
||||
|
||||
/** Frame buffer max address */
|
||||
Addr maxAddr;
|
||||
|
||||
/** Frame buffer current address */
|
||||
Addr curAddr;
|
||||
|
||||
/** DMA FIFO watermark */
|
||||
int waterMark;
|
||||
|
||||
/** Number of pending dma reads */
|
||||
int dmaPendingNum;
|
||||
|
||||
/** Send updated parameters to the vnc server */
|
||||
void updateVideoParams();
|
||||
|
||||
/** DMA framebuffer read */
|
||||
void readFramebuffer();
|
||||
|
||||
/** Generate dma framebuffer read event */
|
||||
void generateReadEvent();
|
||||
|
||||
/** Function to generate interrupt */
|
||||
void generateInterrupt();
|
||||
|
||||
/** fillFIFO event */
|
||||
void fillFifo();
|
||||
|
||||
/** start the dmas off after power is enabled */
|
||||
void startDma();
|
||||
|
||||
/** DMA done event */
|
||||
void dmaDone();
|
||||
|
||||
/** Next cycle event */
|
||||
Tick nextCycle();
|
||||
Tick nextCycle(Tick beginTick);
|
||||
|
||||
/** DMA framebuffer read event */
|
||||
EventWrapper<Pl111, &Pl111::readFramebuffer> readEvent;
|
||||
|
||||
/** Fill fifo */
|
||||
EventWrapper<Pl111, &Pl111::fillFifo> fillFifoEvent;
|
||||
|
||||
/** DMA done event */
|
||||
std::vector<EventWrapper<Pl111, &Pl111::dmaDone> > dmaDoneEvent;
|
||||
|
||||
/** Wrapper to create an event out of the interrupt */
|
||||
EventWrapper<Pl111, &Pl111::generateInterrupt> intEvent;
|
||||
|
||||
public:
|
||||
typedef Pl111Params Params;
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
Pl111(const Params *p);
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
/**
|
||||
* Determine the address ranges that this device responds to.
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
AddrRangeList getAddrRanges();
|
||||
};
|
||||
|
||||
#endif
|
||||
122
simulators/gem5/src/dev/arm/realview.cc
Normal file
122
simulators/gem5/src/dev/arm/realview.cc
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2009 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Implementation of RealView platform.
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "config/the_isa.hh"
|
||||
#include "cpu/intr_control.hh"
|
||||
#include "dev/arm/gic.hh"
|
||||
#include "dev/arm/realview.hh"
|
||||
#include "dev/terminal.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
using namespace std;
|
||||
using namespace TheISA;
|
||||
|
||||
RealView::RealView(const Params *p)
|
||||
: Platform(p), system(p->system)
|
||||
{}
|
||||
|
||||
void
|
||||
RealView::postConsoleInt()
|
||||
{
|
||||
warn_once("Don't know what interrupt to post for console.\n");
|
||||
//panic("Need implementation\n");
|
||||
}
|
||||
|
||||
void
|
||||
RealView::clearConsoleInt()
|
||||
{
|
||||
warn_once("Don't know what interrupt to clear for console.\n");
|
||||
//panic("Need implementation\n");
|
||||
}
|
||||
|
||||
void
|
||||
RealView::postPciInt(int line)
|
||||
{
|
||||
gic->sendInt(line);
|
||||
}
|
||||
|
||||
void
|
||||
RealView::clearPciInt(int line)
|
||||
{
|
||||
gic->clearInt(line);
|
||||
}
|
||||
|
||||
Addr
|
||||
RealView::pciToDma(Addr pciAddr) const
|
||||
{
|
||||
return pciAddr;
|
||||
}
|
||||
|
||||
|
||||
Addr
|
||||
RealView::calcPciConfigAddr(int bus, int dev, int func)
|
||||
{
|
||||
if (bus != 0)
|
||||
return ULL(-1);
|
||||
return params()->pci_cfg_base | ((func & 7) << 16) | ((dev & 0x1f) << 19);
|
||||
}
|
||||
|
||||
Addr
|
||||
RealView::calcPciIOAddr(Addr addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
Addr
|
||||
RealView::calcPciMemAddr(Addr addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
RealView *
|
||||
RealViewParams::create()
|
||||
{
|
||||
return new RealView(this);
|
||||
}
|
||||
123
simulators/gem5/src/dev/arm/realview.hh
Normal file
123
simulators/gem5/src/dev/arm/realview.hh
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2009 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Declaration of top level class for the RealView platform chips. This class just
|
||||
* retains pointers to all its children so the children can communicate.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_RealView_HH__
|
||||
#define __DEV_ARM_RealView_HH__
|
||||
|
||||
#include "dev/platform.hh"
|
||||
#include "params/RealView.hh"
|
||||
|
||||
class IdeController;
|
||||
class System;
|
||||
|
||||
class RealView : public Platform
|
||||
{
|
||||
public:
|
||||
/** Pointer to the system */
|
||||
System *system;
|
||||
|
||||
Gic *gic;
|
||||
|
||||
public:
|
||||
typedef RealViewParams Params;
|
||||
const Params *
|
||||
params() const {
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for the Tsunami Class.
|
||||
* @param name name of the object
|
||||
* @param s system the object belongs to
|
||||
* @param intctrl pointer to the interrupt controller
|
||||
*/
|
||||
RealView(const Params *p);
|
||||
|
||||
/** Give platform a pointer to interrupt controller */
|
||||
void setGic(Gic *_gic) { gic = _gic; }
|
||||
|
||||
/**
|
||||
* Cause the cpu to post a serial interrupt to the CPU.
|
||||
*/
|
||||
virtual void postConsoleInt();
|
||||
|
||||
/**
|
||||
* Clear a posted CPU interrupt
|
||||
*/
|
||||
virtual void clearConsoleInt();
|
||||
|
||||
/**
|
||||
* Cause the chipset to post a cpi interrupt to the CPU.
|
||||
*/
|
||||
virtual void postPciInt(int line);
|
||||
|
||||
/**
|
||||
* Clear a posted PCI->CPU interrupt
|
||||
*/
|
||||
virtual void clearPciInt(int line);
|
||||
|
||||
|
||||
virtual Addr pciToDma(Addr pciAddr) const;
|
||||
|
||||
/**
|
||||
* Calculate the configuration address given a bus/dev/func.
|
||||
*/
|
||||
virtual Addr calcPciConfigAddr(int bus, int dev, int func);
|
||||
|
||||
/**
|
||||
* Calculate the address for an IO location on the PCI bus.
|
||||
*/
|
||||
virtual Addr calcPciIOAddr(Addr addr);
|
||||
|
||||
/**
|
||||
* Calculate the address for a memory location on the PCI bus.
|
||||
*/
|
||||
virtual Addr calcPciMemAddr(Addr addr);
|
||||
};
|
||||
|
||||
#endif // __DEV_ARM_RealView_HH__
|
||||
251
simulators/gem5/src/dev/arm/rtc_pl031.cc
Normal file
251
simulators/gem5/src/dev/arm/rtc_pl031.cc
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2012 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "base/intmath.hh"
|
||||
#include "base/time.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/Checkpoint.hh"
|
||||
#include "debug/Timer.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "dev/arm/rtc_pl031.hh"
|
||||
#include "dev/mc146818.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
using namespace AmbaDev;
|
||||
|
||||
PL031::PL031(Params *p)
|
||||
: AmbaIntDevice(p), timeVal(mkutctime(&p->time)), lastWrittenTick(0),
|
||||
loadVal(0), matchVal(0), rawInt(false), maskInt(false),
|
||||
pendingInt(false), matchEvent(this)
|
||||
{
|
||||
pioSize = 0xfff;
|
||||
}
|
||||
|
||||
|
||||
Tick
|
||||
PL031::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == 4);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
uint32_t data;
|
||||
|
||||
DPRINTF(Timer, "Reading from RTC at offset: %#x\n", daddr);
|
||||
|
||||
switch (daddr) {
|
||||
case DataReg:
|
||||
data = timeVal + ((curTick() - lastWrittenTick) / SimClock::Int::s);
|
||||
break;
|
||||
case MatchReg:
|
||||
data = matchVal;
|
||||
break;
|
||||
case LoadReg:
|
||||
data = loadVal;
|
||||
break;
|
||||
case ControlReg:
|
||||
data = 1; // Always enabled otherwise there is no point
|
||||
break;
|
||||
case IntMask:
|
||||
data = maskInt;
|
||||
break;
|
||||
case RawISR:
|
||||
data = rawInt;
|
||||
break;
|
||||
case MaskedISR:
|
||||
data = pendingInt;
|
||||
break;
|
||||
default:
|
||||
if (AmbaDev::readId(pkt, ambaId, pioAddr)) {
|
||||
// Hack for variable sized access
|
||||
data = pkt->get<uint32_t>();
|
||||
break;
|
||||
}
|
||||
panic("Tried to read PL031 at offset %#x that doesn't exist\n", daddr);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(pkt->getSize()) {
|
||||
case 1:
|
||||
pkt->set<uint8_t>(data);
|
||||
break;
|
||||
case 2:
|
||||
pkt->set<uint16_t>(data);
|
||||
break;
|
||||
case 4:
|
||||
pkt->set<uint32_t>(data);
|
||||
break;
|
||||
default:
|
||||
panic("Uart read size too big?\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
PL031::write(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == 4);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
DPRINTF(Timer, "Writing to RTC at offset: %#x\n", daddr);
|
||||
|
||||
switch (daddr) {
|
||||
case DataReg:
|
||||
break;
|
||||
case MatchReg:
|
||||
matchVal = pkt->get<uint32_t>();
|
||||
resyncMatch();
|
||||
break;
|
||||
case LoadReg:
|
||||
lastWrittenTick = curTick();
|
||||
timeVal = pkt->get<uint32_t>();
|
||||
loadVal = timeVal;
|
||||
resyncMatch();
|
||||
break;
|
||||
case ControlReg:
|
||||
break; // Can't stop when started
|
||||
case IntMask:
|
||||
maskInt = pkt->get<uint32_t>();
|
||||
break;
|
||||
case IntClear:
|
||||
if (pkt->get<uint32_t>()) {
|
||||
rawInt = false;
|
||||
pendingInt = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (AmbaDev::readId(pkt, ambaId, pioAddr))
|
||||
break;
|
||||
panic("Tried to read PL031 at offset %#x that doesn't exist\n", daddr);
|
||||
break;
|
||||
}
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
PL031::resyncMatch()
|
||||
{
|
||||
DPRINTF(Timer, "Setting up new match event match=%d time=%d\n", matchVal,
|
||||
timeVal);
|
||||
|
||||
uint32_t seconds_until = matchVal - timeVal;
|
||||
Tick ticks_until = SimClock::Int::s * seconds_until;
|
||||
|
||||
if (matchEvent.scheduled()) {
|
||||
DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
|
||||
deschedule(matchEvent);
|
||||
}
|
||||
schedule(matchEvent, curTick() + ticks_until);
|
||||
DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + ticks_until);
|
||||
}
|
||||
|
||||
void
|
||||
PL031::counterMatch()
|
||||
{
|
||||
DPRINTF(Timer, "Counter reached zero\n");
|
||||
|
||||
rawInt = true;
|
||||
bool old_pending = pendingInt;
|
||||
pendingInt = maskInt & rawInt;
|
||||
if (pendingInt && !old_pending) {
|
||||
DPRINTF(Timer, "-- Causing interrupt\n");
|
||||
gic->sendInt(intNum);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PL031::serialize(std::ostream &os)
|
||||
{
|
||||
DPRINTF(Checkpoint, "Serializing Arm PL031\n");
|
||||
SERIALIZE_SCALAR(timeVal);
|
||||
SERIALIZE_SCALAR(lastWrittenTick);
|
||||
SERIALIZE_SCALAR(loadVal);
|
||||
SERIALIZE_SCALAR(matchVal);
|
||||
SERIALIZE_SCALAR(rawInt);
|
||||
SERIALIZE_SCALAR(maskInt);
|
||||
SERIALIZE_SCALAR(pendingInt);
|
||||
|
||||
bool is_in_event = matchEvent.scheduled();
|
||||
SERIALIZE_SCALAR(is_in_event);
|
||||
|
||||
Tick event_time;
|
||||
if (is_in_event){
|
||||
event_time = matchEvent.when();
|
||||
SERIALIZE_SCALAR(event_time);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PL031::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
DPRINTF(Checkpoint, "Unserializing Arm PL031\n");
|
||||
|
||||
UNSERIALIZE_SCALAR(timeVal);
|
||||
UNSERIALIZE_SCALAR(lastWrittenTick);
|
||||
UNSERIALIZE_SCALAR(loadVal);
|
||||
UNSERIALIZE_SCALAR(matchVal);
|
||||
UNSERIALIZE_SCALAR(rawInt);
|
||||
UNSERIALIZE_SCALAR(maskInt);
|
||||
UNSERIALIZE_SCALAR(pendingInt);
|
||||
|
||||
bool is_in_event;
|
||||
UNSERIALIZE_SCALAR(is_in_event);
|
||||
|
||||
Tick event_time;
|
||||
if (is_in_event){
|
||||
UNSERIALIZE_SCALAR(event_time);
|
||||
schedule(matchEvent, event_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PL031 *
|
||||
PL031Params::create()
|
||||
{
|
||||
return new PL031(this);
|
||||
}
|
||||
136
simulators/gem5/src/dev/arm/rtc_pl031.hh
Normal file
136
simulators/gem5/src/dev/arm/rtc_pl031.hh
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2012 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_RTC_PL310_HH__
|
||||
#define __DEV_ARM_RTC_PL310_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "params/PL031.hh"
|
||||
|
||||
/** @file
|
||||
* This implements the ARM Primecell 031 RTC
|
||||
*/
|
||||
|
||||
class PL031 : public AmbaIntDevice
|
||||
{
|
||||
protected:
|
||||
enum {
|
||||
DataReg = 0x00,
|
||||
MatchReg = 0x04,
|
||||
LoadReg = 0x08,
|
||||
ControlReg = 0x0C,
|
||||
IntMask = 0x10,
|
||||
RawISR = 0x14,
|
||||
MaskedISR = 0x18,
|
||||
IntClear = 0x1C,
|
||||
};
|
||||
|
||||
/* Seconds since epoch that correspond to time simulation was started at the
|
||||
* begining of simulation and is then updated if ever written. */
|
||||
uint32_t timeVal;
|
||||
|
||||
/* Time when the timeVal register was written */
|
||||
Tick lastWrittenTick;
|
||||
|
||||
/* Previous load value */
|
||||
uint32_t loadVal;
|
||||
|
||||
/* RTC Match Value
|
||||
* Cause an interrupt when this value hits counter
|
||||
*/
|
||||
uint32_t matchVal;
|
||||
|
||||
/** If timer has caused an interrupt. This is irrespective of
|
||||
* interrupt enable */
|
||||
bool rawInt;
|
||||
|
||||
/** If the timer interrupt mask that is anded with the raw interrupt to
|
||||
* generate a pending interrupt
|
||||
*/
|
||||
bool maskInt;
|
||||
|
||||
/** If an interrupt is currently pending. Logical and of CTRL.intEnable
|
||||
* and rawInt */
|
||||
bool pendingInt;
|
||||
|
||||
/** Called when the counter reaches matches */
|
||||
void counterMatch();
|
||||
EventWrapper<PL031, &PL031::counterMatch> matchEvent;
|
||||
|
||||
/** Called to update the matchEvent when the load Value or match value are
|
||||
* written.
|
||||
*/
|
||||
void resyncMatch();
|
||||
|
||||
public:
|
||||
typedef PL031Params Params;
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
/**
|
||||
* The constructor for RealView just registers itself with the MMU.
|
||||
* @param p params structure
|
||||
*/
|
||||
PL031(Params *p);
|
||||
|
||||
/**
|
||||
* Handle a read to the device
|
||||
* @param pkt The memory request.
|
||||
* @param data Where to put the data.
|
||||
*/
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* Handle writes to the device
|
||||
* @param pkt The memory request.
|
||||
* @param data the data
|
||||
*/
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
|
||||
#endif // __DEV_ARM_RTC_PL031_HH__
|
||||
|
||||
168
simulators/gem5/src/dev/arm/rv_ctrl.cc
Normal file
168
simulators/gem5/src/dev/arm/rv_ctrl.cc
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "dev/arm/rv_ctrl.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
RealViewCtrl::RealViewCtrl(Params *p)
|
||||
: BasicPioDevice(p), flags(0)
|
||||
{
|
||||
pioSize = 0xD4;
|
||||
}
|
||||
|
||||
Tick
|
||||
RealViewCtrl::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == 4);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
|
||||
switch(daddr) {
|
||||
case ProcId0:
|
||||
pkt->set(params()->proc_id0);
|
||||
break;
|
||||
case ProcId1:
|
||||
pkt->set(params()->proc_id1);
|
||||
break;
|
||||
case Clock24:
|
||||
Tick clk;
|
||||
clk = SimClock::Float::MHz * curTick() * 24;
|
||||
pkt->set((uint32_t)(clk));
|
||||
break;
|
||||
case Clock100:
|
||||
Tick clk100;
|
||||
clk100 = SimClock::Float::MHz * curTick() * 100;
|
||||
pkt->set((uint32_t)(clk100));
|
||||
break;
|
||||
case Flash:
|
||||
pkt->set<uint32_t>(0);
|
||||
break;
|
||||
case Clcd:
|
||||
pkt->set<uint32_t>(0x00001F00);
|
||||
break;
|
||||
case Osc0:
|
||||
pkt->set<uint32_t>(0x00012C5C);
|
||||
break;
|
||||
case Osc1:
|
||||
pkt->set<uint32_t>(0x00002CC0);
|
||||
break;
|
||||
case Osc2:
|
||||
pkt->set<uint32_t>(0x00002C75);
|
||||
break;
|
||||
case Osc3:
|
||||
pkt->set<uint32_t>(0x00020211);
|
||||
break;
|
||||
case Osc4:
|
||||
pkt->set<uint32_t>(0x00002C75);
|
||||
break;
|
||||
case Lock:
|
||||
pkt->set<uint32_t>(sysLock);
|
||||
break;
|
||||
case Flags:
|
||||
pkt->set<uint32_t>(flags);
|
||||
break;
|
||||
case IdReg:
|
||||
pkt->set<uint32_t>(params()->idreg);
|
||||
break;
|
||||
case CfgStat:
|
||||
pkt->set<uint32_t>(1);
|
||||
break;
|
||||
default:
|
||||
warn("Tried to read RealView I/O at offset %#x that doesn't exist\n",
|
||||
daddr);
|
||||
break;
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
|
||||
}
|
||||
|
||||
Tick
|
||||
RealViewCtrl::write(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
switch (daddr) {
|
||||
case Flash:
|
||||
case Clcd:
|
||||
case Osc0:
|
||||
case Osc1:
|
||||
case Osc2:
|
||||
case Osc3:
|
||||
case Osc4:
|
||||
break;
|
||||
case Lock:
|
||||
sysLock.lockVal = pkt->get<uint16_t>();
|
||||
break;
|
||||
case Flags:
|
||||
flags = pkt->get<uint32_t>();
|
||||
break;
|
||||
case FlagsClr:
|
||||
flags = 0;
|
||||
break;
|
||||
default:
|
||||
warn("Tried to write RVIO at offset %#x that doesn't exist\n",
|
||||
daddr);
|
||||
break;
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
RealViewCtrl::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(flags);
|
||||
}
|
||||
|
||||
void
|
||||
RealViewCtrl::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(flags);
|
||||
}
|
||||
|
||||
RealViewCtrl *
|
||||
RealViewCtrlParams::create()
|
||||
{
|
||||
return new RealViewCtrl(this);
|
||||
}
|
||||
142
simulators/gem5/src/dev/arm/rv_ctrl.hh
Normal file
142
simulators/gem5/src/dev/arm/rv_ctrl.hh
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_RV_HH__
|
||||
#define __DEV_ARM_RV_HH__
|
||||
|
||||
#include "base/bitunion.hh"
|
||||
#include "base/range.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "params/RealViewCtrl.hh"
|
||||
|
||||
/** @file
|
||||
* This implements the simple real view registers on a PBXA9
|
||||
*/
|
||||
|
||||
class RealViewCtrl : public BasicPioDevice
|
||||
{
|
||||
protected:
|
||||
enum {
|
||||
IdReg = 0x00,
|
||||
SwReg = 0x04,
|
||||
Led = 0x08,
|
||||
Osc0 = 0x0C,
|
||||
Osc1 = 0x10,
|
||||
Osc2 = 0x14,
|
||||
Osc3 = 0x18,
|
||||
Osc4 = 0x1C,
|
||||
Lock = 0x20,
|
||||
Clock100 = 0x24,
|
||||
CfgData1 = 0x28,
|
||||
CfgData2 = 0x2C,
|
||||
Flags = 0x30,
|
||||
FlagsClr = 0x34,
|
||||
NvFlags = 0x38,
|
||||
NvFlagsClr = 0x3C,
|
||||
ResetCtl = 0x40,
|
||||
PciCtl = 0x44,
|
||||
MciCtl = 0x48,
|
||||
Flash = 0x4C,
|
||||
Clcd = 0x50,
|
||||
ClcdSer = 0x54,
|
||||
Bootcs = 0x58,
|
||||
Clock24 = 0x5C,
|
||||
Misc = 0x60,
|
||||
IoSel = 0x70,
|
||||
ProcId0 = 0x84,
|
||||
ProcId1 = 0x88,
|
||||
CfgCtrl = 0xA0,
|
||||
CfgData = 0xA4,
|
||||
CfgStat = 0xA8,
|
||||
TestOsc0 = 0xC0,
|
||||
TestOsc1 = 0xC4,
|
||||
TestOsc2 = 0xC8,
|
||||
TestOsc3 = 0xCC,
|
||||
TestOsc4 = 0xD0
|
||||
};
|
||||
|
||||
// system lock value
|
||||
BitUnion32(SysLockReg)
|
||||
Bitfield<15,0> lockVal;
|
||||
Bitfield<16> locked;
|
||||
EndBitUnion(SysLockReg)
|
||||
|
||||
SysLockReg sysLock;
|
||||
|
||||
/** This register is used for smp booting.
|
||||
* The primary cpu writes the secondary start address here before
|
||||
* sends it a soft interrupt. The secondary cpu reads this register and if
|
||||
* it's non-zero it jumps to the address
|
||||
*/
|
||||
uint32_t flags;
|
||||
|
||||
public:
|
||||
typedef RealViewCtrlParams Params;
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
/**
|
||||
* The constructor for RealView just registers itself with the MMU.
|
||||
* @param p params structure
|
||||
*/
|
||||
RealViewCtrl(Params *p);
|
||||
|
||||
/**
|
||||
* Handle a read to the device
|
||||
* @param pkt The memory request.
|
||||
* @param data Where to put the data.
|
||||
*/
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* All writes are simply ignored.
|
||||
* @param pkt The memory request.
|
||||
* @param data the data
|
||||
*/
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
|
||||
#endif // __DEV_ARM_RV_HH__
|
||||
440
simulators/gem5/src/dev/arm/timer_cpulocal.cc
Normal file
440
simulators/gem5/src/dev/arm/timer_cpulocal.cc
Normal file
@ -0,0 +1,440 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
* Geoffrey Blake
|
||||
*/
|
||||
|
||||
#include "base/intmath.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/Checkpoint.hh"
|
||||
#include "debug/Timer.hh"
|
||||
#include "dev/arm/gic.hh"
|
||||
#include "dev/arm/timer_cpulocal.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
CpuLocalTimer::CpuLocalTimer(Params *p)
|
||||
: BasicPioDevice(p), gic(p->gic)
|
||||
{
|
||||
// Initialize the timer registers for each per cpu timer
|
||||
for (int i = 0; i < CPU_MAX; i++) {
|
||||
std::stringstream oss;
|
||||
oss << name() << ".timer" << i;
|
||||
localTimer[i]._name = oss.str();
|
||||
localTimer[i].parent = this;
|
||||
localTimer[i].intNumTimer = p->int_num_timer;
|
||||
localTimer[i].intNumWatchdog = p->int_num_watchdog;
|
||||
localTimer[i].clock = p->clock;
|
||||
localTimer[i].cpuNum = i;
|
||||
}
|
||||
pioSize = 0x38;
|
||||
}
|
||||
|
||||
CpuLocalTimer::Timer::Timer()
|
||||
: timerControl(0x0), watchdogControl(0x0), rawIntTimer(false), rawIntWatchdog(false),
|
||||
rawResetWatchdog(false), watchdogDisableReg(0x0), pendingIntTimer(false), pendingIntWatchdog(false),
|
||||
timerLoadValue(0x0), watchdogLoadValue(0x0), timerZeroEvent(this), watchdogZeroEvent(this)
|
||||
{
|
||||
}
|
||||
|
||||
Tick
|
||||
CpuLocalTimer::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == 4);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
int cpu_id = pkt->req->contextId();
|
||||
DPRINTF(Timer, "Reading from CpuLocalTimer at offset: %#x\n", daddr);
|
||||
assert(cpu_id >= 0);
|
||||
assert(cpu_id < CPU_MAX);
|
||||
|
||||
if (daddr < Timer::Size)
|
||||
localTimer[cpu_id].read(pkt, daddr);
|
||||
else
|
||||
panic("Tried to read CpuLocalTimer at offset %#x that doesn't exist\n", daddr);
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CpuLocalTimer::Timer::read(PacketPtr pkt, Addr daddr)
|
||||
{
|
||||
DPRINTF(Timer, "Reading from CpuLocalTimer at offset: %#x\n", daddr);
|
||||
Tick time;
|
||||
|
||||
switch(daddr) {
|
||||
case TimerLoadReg:
|
||||
pkt->set<uint32_t>(timerLoadValue);
|
||||
break;
|
||||
case TimerCounterReg:
|
||||
DPRINTF(Timer, "Event schedule for timer %d, clock=%d, prescale=%d\n",
|
||||
timerZeroEvent.when(), clock, timerControl.prescalar);
|
||||
time = timerZeroEvent.when() - curTick();
|
||||
time = time / clock / power(16, timerControl.prescalar);
|
||||
DPRINTF(Timer, "-- returning counter at %d\n", time);
|
||||
pkt->set<uint32_t>(time);
|
||||
break;
|
||||
case TimerControlReg:
|
||||
pkt->set<uint32_t>(timerControl);
|
||||
break;
|
||||
case TimerIntStatusReg:
|
||||
pkt->set<uint32_t>(rawIntTimer);
|
||||
break;
|
||||
case WatchdogLoadReg:
|
||||
pkt->set<uint32_t>(watchdogLoadValue);
|
||||
break;
|
||||
case WatchdogCounterReg:
|
||||
DPRINTF(Timer, "Event schedule for watchdog %d, clock=%d, prescale=%d\n",
|
||||
watchdogZeroEvent.when(), clock, watchdogControl.prescalar);
|
||||
time = watchdogZeroEvent.when() - curTick();
|
||||
time = time / clock / power(16, watchdogControl.prescalar);
|
||||
DPRINTF(Timer, "-- returning counter at %d\n", time);
|
||||
pkt->set<uint32_t>(time);
|
||||
break;
|
||||
case WatchdogControlReg:
|
||||
pkt->set<uint32_t>(watchdogControl);
|
||||
break;
|
||||
case WatchdogIntStatusReg:
|
||||
pkt->set<uint32_t>(rawIntWatchdog);
|
||||
break;
|
||||
case WatchdogResetStatusReg:
|
||||
pkt->set<uint32_t>(rawResetWatchdog);
|
||||
break;
|
||||
case WatchdogDisableReg:
|
||||
panic("Tried to read from WatchdogDisableRegister\n");
|
||||
break;
|
||||
default:
|
||||
panic("Tried to read CpuLocalTimer at offset %#x\n", daddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tick
|
||||
CpuLocalTimer::write(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == 4);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
int cpu_id = pkt->req->contextId();
|
||||
DPRINTF(Timer, "Writing to CpuLocalTimer at offset: %#x\n", daddr);
|
||||
assert(cpu_id >= 0);
|
||||
assert(cpu_id < CPU_MAX);
|
||||
|
||||
if (daddr < Timer::Size)
|
||||
localTimer[cpu_id].write(pkt, daddr);
|
||||
else
|
||||
panic("Tried to write CpuLocalTimer at offset %#x that doesn't exist\n", daddr);
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
CpuLocalTimer::Timer::write(PacketPtr pkt, Addr daddr)
|
||||
{
|
||||
DPRINTF(Timer, "Writing to CpuLocalTimer at offset: %#x\n", daddr);
|
||||
bool old_enable;
|
||||
bool old_wd_mode;
|
||||
uint32_t old_val;
|
||||
|
||||
switch (daddr) {
|
||||
case TimerLoadReg:
|
||||
// Writing to this register also resets the counter register and
|
||||
// starts decrementing if the counter is enabled.
|
||||
timerLoadValue = pkt->get<uint32_t>();
|
||||
restartTimerCounter(timerLoadValue);
|
||||
break;
|
||||
case TimerCounterReg:
|
||||
// Can be written, doesn't start counting unless the timer is enabled
|
||||
restartTimerCounter(pkt->get<uint32_t>());
|
||||
break;
|
||||
case TimerControlReg:
|
||||
old_enable = timerControl.enable;
|
||||
timerControl = pkt->get<uint32_t>();
|
||||
if ((old_enable == 0) && timerControl.enable)
|
||||
restartTimerCounter(timerLoadValue);
|
||||
break;
|
||||
case TimerIntStatusReg:
|
||||
rawIntTimer = false;
|
||||
if (pendingIntTimer) {
|
||||
pendingIntTimer = false;
|
||||
DPRINTF(Timer, "Clearing interrupt\n");
|
||||
}
|
||||
break;
|
||||
case WatchdogLoadReg:
|
||||
watchdogLoadValue = pkt->get<uint32_t>();
|
||||
restartWatchdogCounter(watchdogLoadValue);
|
||||
break;
|
||||
case WatchdogCounterReg:
|
||||
// Can't be written when in watchdog mode, but can in timer mode
|
||||
if (!watchdogControl.watchdogMode) {
|
||||
restartWatchdogCounter(pkt->get<uint32_t>());
|
||||
}
|
||||
break;
|
||||
case WatchdogControlReg:
|
||||
old_enable = watchdogControl.enable;
|
||||
old_wd_mode = watchdogControl.watchdogMode;
|
||||
watchdogControl = pkt->get<uint32_t>();
|
||||
if ((old_enable == 0) && watchdogControl.enable)
|
||||
restartWatchdogCounter(watchdogLoadValue);
|
||||
// cannot disable watchdog using control register
|
||||
if ((old_wd_mode == 1) && watchdogControl.watchdogMode == 0)
|
||||
watchdogControl.watchdogMode = 1;
|
||||
break;
|
||||
case WatchdogIntStatusReg:
|
||||
rawIntWatchdog = false;
|
||||
if (pendingIntWatchdog) {
|
||||
pendingIntWatchdog = false;
|
||||
DPRINTF(Timer, "Clearing watchdog interrupt\n");
|
||||
}
|
||||
break;
|
||||
case WatchdogResetStatusReg:
|
||||
rawResetWatchdog = false;
|
||||
DPRINTF(Timer, "Clearing watchdog reset flag\n");
|
||||
break;
|
||||
case WatchdogDisableReg:
|
||||
old_val = watchdogDisableReg;
|
||||
watchdogDisableReg = pkt->get<uint32_t>();
|
||||
// if this sequence is observed, turn off watchdog mode
|
||||
if (old_val == 0x12345678 && watchdogDisableReg == 0x87654321)
|
||||
watchdogControl.watchdogMode = 0;
|
||||
break;
|
||||
default:
|
||||
panic("Tried to write CpuLocalTimer timer at offset %#x\n", daddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//XXX: Two functions are needed because the control registers are different types
|
||||
void
|
||||
CpuLocalTimer::Timer::restartTimerCounter(uint32_t val)
|
||||
{
|
||||
DPRINTF(Timer, "Resetting timer counter with value %#x\n", val);
|
||||
if (!timerControl.enable)
|
||||
return;
|
||||
|
||||
Tick time = clock * power(16, timerControl.prescalar);
|
||||
time *= val;
|
||||
|
||||
if (timerZeroEvent.scheduled()) {
|
||||
DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
|
||||
parent->deschedule(timerZeroEvent);
|
||||
}
|
||||
parent->schedule(timerZeroEvent, curTick() + time);
|
||||
DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time);
|
||||
}
|
||||
|
||||
void
|
||||
CpuLocalTimer::Timer::restartWatchdogCounter(uint32_t val)
|
||||
{
|
||||
DPRINTF(Timer, "Resetting watchdog counter with value %#x\n", val);
|
||||
if (!watchdogControl.enable)
|
||||
return;
|
||||
|
||||
Tick time = clock * power(16, watchdogControl.prescalar);
|
||||
time *= val;
|
||||
|
||||
if (watchdogZeroEvent.scheduled()) {
|
||||
DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
|
||||
parent->deschedule(watchdogZeroEvent);
|
||||
}
|
||||
parent->schedule(watchdogZeroEvent, curTick() + time);
|
||||
DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time);
|
||||
}
|
||||
//////
|
||||
|
||||
void
|
||||
CpuLocalTimer::Timer::timerAtZero()
|
||||
{
|
||||
if (!timerControl.enable)
|
||||
return;
|
||||
|
||||
DPRINTF(Timer, "Timer Counter reached zero\n");
|
||||
|
||||
rawIntTimer = true;
|
||||
bool old_pending = pendingIntTimer;
|
||||
if (timerControl.intEnable)
|
||||
pendingIntTimer = true;
|
||||
if (pendingIntTimer && !old_pending) {
|
||||
DPRINTF(Timer, "-- Causing interrupt\n");
|
||||
parent->gic->sendPPInt(intNumTimer, cpuNum);
|
||||
}
|
||||
|
||||
if (!timerControl.autoReload)
|
||||
return;
|
||||
else
|
||||
restartTimerCounter(timerLoadValue);
|
||||
}
|
||||
|
||||
void
|
||||
CpuLocalTimer::Timer::watchdogAtZero()
|
||||
{
|
||||
if (!watchdogControl.enable)
|
||||
return;
|
||||
|
||||
DPRINTF(Timer, "Watchdog Counter reached zero\n");
|
||||
|
||||
rawIntWatchdog = true;
|
||||
bool old_pending = pendingIntWatchdog;
|
||||
// generates an interrupt only if the watchdog is in timer
|
||||
// mode.
|
||||
if (watchdogControl.intEnable && !watchdogControl.watchdogMode)
|
||||
pendingIntWatchdog = true;
|
||||
else if (watchdogControl.watchdogMode) {
|
||||
rawResetWatchdog = true;
|
||||
fatal("gem5 ARM Model does not support true watchdog operation!\n");
|
||||
//XXX: Should we ever support a true watchdog reset?
|
||||
}
|
||||
|
||||
if (pendingIntWatchdog && !old_pending) {
|
||||
DPRINTF(Timer, "-- Causing interrupt\n");
|
||||
parent->gic->sendPPInt(intNumWatchdog, cpuNum);
|
||||
}
|
||||
|
||||
if (watchdogControl.watchdogMode)
|
||||
return;
|
||||
else if (watchdogControl.autoReload)
|
||||
restartWatchdogCounter(watchdogLoadValue);
|
||||
}
|
||||
|
||||
void
|
||||
CpuLocalTimer::Timer::serialize(std::ostream &os)
|
||||
{
|
||||
DPRINTF(Checkpoint, "Serializing Arm CpuLocalTimer\n");
|
||||
SERIALIZE_SCALAR(intNumTimer);
|
||||
SERIALIZE_SCALAR(intNumWatchdog);
|
||||
SERIALIZE_SCALAR(clock);
|
||||
|
||||
uint32_t timer_control_serial = timerControl;
|
||||
uint32_t watchdog_control_serial = watchdogControl;
|
||||
SERIALIZE_SCALAR(timer_control_serial);
|
||||
SERIALIZE_SCALAR(watchdog_control_serial);
|
||||
|
||||
SERIALIZE_SCALAR(rawIntTimer);
|
||||
SERIALIZE_SCALAR(rawIntWatchdog);
|
||||
SERIALIZE_SCALAR(rawResetWatchdog);
|
||||
SERIALIZE_SCALAR(watchdogDisableReg);
|
||||
SERIALIZE_SCALAR(pendingIntTimer);
|
||||
SERIALIZE_SCALAR(pendingIntWatchdog);
|
||||
SERIALIZE_SCALAR(timerLoadValue);
|
||||
SERIALIZE_SCALAR(watchdogLoadValue);
|
||||
|
||||
bool timer_is_in_event = timerZeroEvent.scheduled();
|
||||
SERIALIZE_SCALAR(timer_is_in_event);
|
||||
bool watchdog_is_in_event = watchdogZeroEvent.scheduled();
|
||||
SERIALIZE_SCALAR(watchdog_is_in_event);
|
||||
|
||||
Tick timer_event_time;
|
||||
if (timer_is_in_event){
|
||||
timer_event_time = timerZeroEvent.when();
|
||||
SERIALIZE_SCALAR(timer_event_time);
|
||||
}
|
||||
Tick watchdog_event_time;
|
||||
if (watchdog_is_in_event){
|
||||
watchdog_event_time = watchdogZeroEvent.when();
|
||||
SERIALIZE_SCALAR(watchdog_event_time);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CpuLocalTimer::Timer::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
DPRINTF(Checkpoint, "Unserializing Arm CpuLocalTimer\n");
|
||||
|
||||
UNSERIALIZE_SCALAR(intNumTimer);
|
||||
UNSERIALIZE_SCALAR(intNumWatchdog);
|
||||
UNSERIALIZE_SCALAR(clock);
|
||||
|
||||
uint32_t timer_control_serial;
|
||||
UNSERIALIZE_SCALAR(timer_control_serial);
|
||||
timerControl = timer_control_serial;
|
||||
uint32_t watchdog_control_serial;
|
||||
UNSERIALIZE_SCALAR(watchdog_control_serial);
|
||||
watchdogControl = watchdog_control_serial;
|
||||
|
||||
UNSERIALIZE_SCALAR(rawIntTimer);
|
||||
UNSERIALIZE_SCALAR(rawIntWatchdog);
|
||||
UNSERIALIZE_SCALAR(rawResetWatchdog);
|
||||
UNSERIALIZE_SCALAR(watchdogDisableReg);
|
||||
UNSERIALIZE_SCALAR(pendingIntTimer);
|
||||
UNSERIALIZE_SCALAR(pendingIntWatchdog);
|
||||
UNSERIALIZE_SCALAR(timerLoadValue);
|
||||
UNSERIALIZE_SCALAR(watchdogLoadValue);
|
||||
|
||||
bool timer_is_in_event;
|
||||
UNSERIALIZE_SCALAR(timer_is_in_event);
|
||||
bool watchdog_is_in_event;
|
||||
UNSERIALIZE_SCALAR(watchdog_is_in_event);
|
||||
|
||||
Tick timer_event_time;
|
||||
if (timer_is_in_event){
|
||||
UNSERIALIZE_SCALAR(timer_event_time);
|
||||
parent->schedule(timerZeroEvent, timer_event_time);
|
||||
}
|
||||
Tick watchdog_event_time;
|
||||
if (watchdog_is_in_event) {
|
||||
UNSERIALIZE_SCALAR(watchdog_event_time);
|
||||
parent->schedule(watchdogZeroEvent, watchdog_event_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CpuLocalTimer::serialize(std::ostream &os)
|
||||
{
|
||||
for (int i = 0; i < CPU_MAX; i++) {
|
||||
nameOut(os, csprintf("%s.timer%d", name(), i));
|
||||
localTimer[i].serialize(os);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CpuLocalTimer::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
for (int i = 0; i < CPU_MAX; i++) {
|
||||
localTimer[i].unserialize(cp, csprintf("%s.timer%d", section, i));
|
||||
}
|
||||
}
|
||||
|
||||
CpuLocalTimer *
|
||||
CpuLocalTimerParams::create()
|
||||
{
|
||||
return new CpuLocalTimer(this);
|
||||
}
|
||||
199
simulators/gem5/src/dev/arm/timer_cpulocal.hh
Normal file
199
simulators/gem5/src/dev/arm/timer_cpulocal.hh
Normal file
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
* Geoffrey Blake
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_LOCALTIMER_HH__
|
||||
#define __DEV_ARM_LOCALTIMER_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "params/CpuLocalTimer.hh"
|
||||
|
||||
/** @file
|
||||
* This implements the cpu local timer from the Cortex-A9 MPCore
|
||||
* Technical Reference Manual rev r2p2 (ARM DDI 0407F)
|
||||
*/
|
||||
|
||||
class Gic;
|
||||
|
||||
class CpuLocalTimer : public BasicPioDevice
|
||||
{
|
||||
protected:
|
||||
class Timer
|
||||
{
|
||||
|
||||
public:
|
||||
enum {
|
||||
TimerLoadReg = 0x00,
|
||||
TimerCounterReg = 0x04,
|
||||
TimerControlReg = 0x08,
|
||||
TimerIntStatusReg = 0x0C,
|
||||
WatchdogLoadReg = 0x20,
|
||||
WatchdogCounterReg = 0x24,
|
||||
WatchdogControlReg = 0x28,
|
||||
WatchdogIntStatusReg = 0x2C,
|
||||
WatchdogResetStatusReg = 0x30,
|
||||
WatchdogDisableReg = 0x34,
|
||||
Size = 0x38
|
||||
};
|
||||
|
||||
BitUnion32(TimerCtrl)
|
||||
Bitfield<0> enable;
|
||||
Bitfield<1> autoReload;
|
||||
Bitfield<2> intEnable;
|
||||
Bitfield<3,7> reserved;
|
||||
Bitfield<8,15> prescalar;
|
||||
EndBitUnion(TimerCtrl)
|
||||
|
||||
BitUnion32(WatchdogCtrl)
|
||||
Bitfield<0> enable;
|
||||
Bitfield<1> autoReload;
|
||||
Bitfield<2> intEnable;
|
||||
Bitfield<3> watchdogMode;
|
||||
Bitfield<4,7> reserved;
|
||||
Bitfield<8,15> prescalar;
|
||||
EndBitUnion(WatchdogCtrl)
|
||||
|
||||
protected:
|
||||
std::string _name;
|
||||
|
||||
/** Pointer to parent class */
|
||||
CpuLocalTimer *parent;
|
||||
|
||||
/** Number of interrupt to cause/clear */
|
||||
uint32_t intNumTimer;
|
||||
uint32_t intNumWatchdog;
|
||||
|
||||
/** Cpu this timer is attached to */
|
||||
uint32_t cpuNum;
|
||||
|
||||
/** Number of ticks in a clock input */
|
||||
Tick clock;
|
||||
|
||||
/** Control register as specified above */
|
||||
TimerCtrl timerControl;
|
||||
WatchdogCtrl watchdogControl;
|
||||
|
||||
/** If timer has caused an interrupt. This is irrespective of
|
||||
* interrupt enable */
|
||||
bool rawIntTimer;
|
||||
bool rawIntWatchdog;
|
||||
bool rawResetWatchdog;
|
||||
uint32_t watchdogDisableReg;
|
||||
|
||||
/** If an interrupt is currently pending. Logical and of Timer or
|
||||
* Watchdog Ctrl.enable and rawIntTimer or rawIntWatchdog */
|
||||
bool pendingIntTimer;
|
||||
bool pendingIntWatchdog;
|
||||
|
||||
/** Value to load into counters when periodic mode reaches 0 */
|
||||
uint32_t timerLoadValue;
|
||||
uint32_t watchdogLoadValue;
|
||||
|
||||
/** Called when the counter reaches 0 */
|
||||
void timerAtZero();
|
||||
EventWrapper<Timer, &Timer::timerAtZero> timerZeroEvent;
|
||||
|
||||
void watchdogAtZero();
|
||||
EventWrapper<Timer, &Timer::watchdogAtZero> watchdogZeroEvent;
|
||||
public:
|
||||
/** Restart the counter ticking at val
|
||||
* @param val the value to start at */
|
||||
void restartTimerCounter(uint32_t val);
|
||||
void restartWatchdogCounter(uint32_t val);
|
||||
|
||||
Timer();
|
||||
|
||||
std::string name() const { return _name; }
|
||||
|
||||
/** Handle read for a single timer */
|
||||
void read(PacketPtr pkt, Addr daddr);
|
||||
|
||||
/** Handle write for a single timer */
|
||||
void write(PacketPtr pkt, Addr daddr);
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
friend class CpuLocalTimer;
|
||||
};
|
||||
|
||||
static const int CPU_MAX = 8;
|
||||
|
||||
/** Pointer to the GIC for causing an interrupt */
|
||||
Gic *gic;
|
||||
|
||||
/** Timers that do the actual work */
|
||||
Timer localTimer[CPU_MAX];
|
||||
|
||||
public:
|
||||
typedef CpuLocalTimerParams Params;
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
/**
|
||||
* The constructor for RealView just registers itself with the MMU.
|
||||
* @param p params structure
|
||||
*/
|
||||
CpuLocalTimer(Params *p);
|
||||
|
||||
/**
|
||||
* Handle a read to the device
|
||||
* @param pkt The memory request.
|
||||
* @return Returns latency of device read
|
||||
*/
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* Handle a write to the device.
|
||||
* @param pkt The memory request.
|
||||
* @return Returns latency of device write
|
||||
*/
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
|
||||
#endif // __DEV_ARM_SP804_HH__
|
||||
|
||||
295
simulators/gem5/src/dev/arm/timer_sp804.cc
Normal file
295
simulators/gem5/src/dev/arm/timer_sp804.cc
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "base/intmath.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/Checkpoint.hh"
|
||||
#include "debug/Timer.hh"
|
||||
#include "dev/arm/gic.hh"
|
||||
#include "dev/arm/timer_sp804.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
using namespace AmbaDev;
|
||||
|
||||
Sp804::Sp804(Params *p)
|
||||
: AmbaDevice(p), gic(p->gic), timer0(name() + ".timer0", this, p->int_num0, p->clock0),
|
||||
timer1(name() + ".timer1", this, p->int_num1, p->clock1)
|
||||
{
|
||||
pioSize = 0xfff;
|
||||
}
|
||||
|
||||
Sp804::Timer::Timer(std::string __name, Sp804 *_parent, int int_num, Tick _clock)
|
||||
: _name(__name), parent(_parent), intNum(int_num), clock(_clock), control(0x20),
|
||||
rawInt(false), pendingInt(false), loadValue(0xffffffff), zeroEvent(this)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Tick
|
||||
Sp804::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == 4);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
DPRINTF(Timer, "Reading from DualTimer at offset: %#x\n", daddr);
|
||||
|
||||
if (daddr < Timer::Size)
|
||||
timer0.read(pkt, daddr);
|
||||
else if ((daddr - Timer::Size) < Timer::Size)
|
||||
timer1.read(pkt, daddr - Timer::Size);
|
||||
else if (!readId(pkt, ambaId, pioAddr))
|
||||
panic("Tried to read SP804 at offset %#x that doesn't exist\n", daddr);
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Sp804::Timer::read(PacketPtr pkt, Addr daddr)
|
||||
{
|
||||
switch(daddr) {
|
||||
case LoadReg:
|
||||
pkt->set<uint32_t>(loadValue);
|
||||
break;
|
||||
case CurrentReg:
|
||||
DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n",
|
||||
zeroEvent.when(), clock, control.timerPrescale);
|
||||
Tick time;
|
||||
time = zeroEvent.when() - curTick();
|
||||
time = time / clock / power(16, control.timerPrescale);
|
||||
DPRINTF(Timer, "-- returning counter at %d\n", time);
|
||||
pkt->set<uint32_t>(time);
|
||||
break;
|
||||
case ControlReg:
|
||||
pkt->set<uint32_t>(control);
|
||||
break;
|
||||
case RawISR:
|
||||
pkt->set<uint32_t>(rawInt);
|
||||
break;
|
||||
case MaskedISR:
|
||||
pkt->set<uint32_t>(pendingInt);
|
||||
break;
|
||||
case BGLoad:
|
||||
pkt->set<uint32_t>(loadValue);
|
||||
break;
|
||||
default:
|
||||
panic("Tried to read SP804 timer at offset %#x\n", daddr);
|
||||
break;
|
||||
}
|
||||
DPRINTF(Timer, "Reading %#x from Timer at offset: %#x\n", pkt->get<uint32_t>(), daddr);
|
||||
}
|
||||
|
||||
Tick
|
||||
Sp804::write(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == 4);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
DPRINTF(Timer, "Writing to DualTimer at offset: %#x\n", daddr);
|
||||
|
||||
if (daddr < Timer::Size)
|
||||
timer0.write(pkt, daddr);
|
||||
else if ((daddr - Timer::Size) < Timer::Size)
|
||||
timer1.write(pkt, daddr - Timer::Size);
|
||||
else if (!readId(pkt, ambaId, pioAddr))
|
||||
panic("Tried to write SP804 at offset %#x that doesn't exist\n", daddr);
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
Sp804::Timer::write(PacketPtr pkt, Addr daddr)
|
||||
{
|
||||
DPRINTF(Timer, "Writing %#x to Timer at offset: %#x\n", pkt->get<uint32_t>(), daddr);
|
||||
switch (daddr) {
|
||||
case LoadReg:
|
||||
loadValue = pkt->get<uint32_t>();
|
||||
restartCounter(loadValue);
|
||||
break;
|
||||
case CurrentReg:
|
||||
// Spec says this value can't be written, but linux writes it anyway
|
||||
break;
|
||||
case ControlReg:
|
||||
bool old_enable;
|
||||
old_enable = control.timerEnable;
|
||||
control = pkt->get<uint32_t>();
|
||||
if ((old_enable == 0) && control.timerEnable)
|
||||
restartCounter(loadValue);
|
||||
break;
|
||||
case IntClear:
|
||||
rawInt = false;
|
||||
if (pendingInt) {
|
||||
pendingInt = false;
|
||||
DPRINTF(Timer, "Clearing interrupt\n");
|
||||
parent->gic->clearInt(intNum);
|
||||
}
|
||||
break;
|
||||
case BGLoad:
|
||||
loadValue = pkt->get<uint32_t>();
|
||||
break;
|
||||
default:
|
||||
panic("Tried to write SP804 timer at offset %#x\n", daddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Sp804::Timer::restartCounter(uint32_t val)
|
||||
{
|
||||
DPRINTF(Timer, "Resetting counter with value %#x\n", val);
|
||||
if (!control.timerEnable)
|
||||
return;
|
||||
|
||||
Tick time = clock * power(16, control.timerPrescale);
|
||||
if (control.timerSize)
|
||||
time *= val;
|
||||
else
|
||||
time *= bits(val,15,0);
|
||||
|
||||
if (zeroEvent.scheduled()) {
|
||||
DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
|
||||
parent->deschedule(zeroEvent);
|
||||
}
|
||||
parent->schedule(zeroEvent, curTick() + time);
|
||||
DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time);
|
||||
}
|
||||
|
||||
void
|
||||
Sp804::Timer::counterAtZero()
|
||||
{
|
||||
if (!control.timerEnable)
|
||||
return;
|
||||
|
||||
DPRINTF(Timer, "Counter reached zero\n");
|
||||
|
||||
rawInt = true;
|
||||
bool old_pending = pendingInt;
|
||||
if (control.intEnable)
|
||||
pendingInt = true;
|
||||
if (pendingInt && !old_pending) {
|
||||
DPRINTF(Timer, "-- Causing interrupt\n");
|
||||
parent->gic->sendInt(intNum);
|
||||
}
|
||||
|
||||
if (control.oneShot)
|
||||
return;
|
||||
|
||||
// Free-running
|
||||
if (control.timerMode == 0)
|
||||
restartCounter(0xffffffff);
|
||||
else
|
||||
restartCounter(loadValue);
|
||||
}
|
||||
|
||||
void
|
||||
Sp804::Timer::serialize(std::ostream &os)
|
||||
{
|
||||
DPRINTF(Checkpoint, "Serializing Arm Sp804\n");
|
||||
SERIALIZE_SCALAR(intNum);
|
||||
SERIALIZE_SCALAR(clock);
|
||||
|
||||
uint32_t control_serial = control;
|
||||
SERIALIZE_SCALAR(control_serial);
|
||||
|
||||
SERIALIZE_SCALAR(rawInt);
|
||||
SERIALIZE_SCALAR(pendingInt);
|
||||
SERIALIZE_SCALAR(loadValue);
|
||||
|
||||
bool is_in_event = zeroEvent.scheduled();
|
||||
SERIALIZE_SCALAR(is_in_event);
|
||||
|
||||
Tick event_time;
|
||||
if (is_in_event){
|
||||
event_time = zeroEvent.when();
|
||||
SERIALIZE_SCALAR(event_time);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Sp804::Timer::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
DPRINTF(Checkpoint, "Unserializing Arm Sp804\n");
|
||||
|
||||
UNSERIALIZE_SCALAR(intNum);
|
||||
UNSERIALIZE_SCALAR(clock);
|
||||
|
||||
uint32_t control_serial;
|
||||
UNSERIALIZE_SCALAR(control_serial);
|
||||
control = control_serial;
|
||||
|
||||
UNSERIALIZE_SCALAR(rawInt);
|
||||
UNSERIALIZE_SCALAR(pendingInt);
|
||||
UNSERIALIZE_SCALAR(loadValue);
|
||||
|
||||
bool is_in_event;
|
||||
UNSERIALIZE_SCALAR(is_in_event);
|
||||
|
||||
Tick event_time;
|
||||
if (is_in_event){
|
||||
UNSERIALIZE_SCALAR(event_time);
|
||||
parent->schedule(zeroEvent, event_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Sp804::serialize(std::ostream &os)
|
||||
{
|
||||
nameOut(os, csprintf("%s.timer0", name()));
|
||||
timer0.serialize(os);
|
||||
nameOut(os, csprintf("%s.timer1", name()));
|
||||
timer1.serialize(os);
|
||||
}
|
||||
|
||||
void
|
||||
Sp804::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
timer0.unserialize(cp, csprintf("%s.timer0", section));
|
||||
timer1.unserialize(cp, csprintf("%s.timer1", section));
|
||||
}
|
||||
|
||||
Sp804 *
|
||||
Sp804Params::create()
|
||||
{
|
||||
return new Sp804(this);
|
||||
}
|
||||
171
simulators/gem5/src/dev/arm/timer_sp804.hh
Normal file
171
simulators/gem5/src/dev/arm/timer_sp804.hh
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_SP804_HH__
|
||||
#define __DEV_ARM_SP804_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "params/Sp804.hh"
|
||||
|
||||
/** @file
|
||||
* This implements the dual Sp804 timer block
|
||||
*/
|
||||
|
||||
class Gic;
|
||||
|
||||
class Sp804 : public AmbaDevice
|
||||
{
|
||||
protected:
|
||||
class Timer
|
||||
{
|
||||
|
||||
public:
|
||||
enum {
|
||||
LoadReg = 0x00,
|
||||
CurrentReg = 0x04,
|
||||
ControlReg = 0x08,
|
||||
IntClear = 0x0C,
|
||||
RawISR = 0x10,
|
||||
MaskedISR = 0x14,
|
||||
BGLoad = 0x18,
|
||||
Size = 0x20
|
||||
};
|
||||
|
||||
BitUnion32(CTRL)
|
||||
Bitfield<0> oneShot;
|
||||
Bitfield<1> timerSize;
|
||||
Bitfield<3,2> timerPrescale;
|
||||
Bitfield<5> intEnable;
|
||||
Bitfield<6> timerMode;
|
||||
Bitfield<7> timerEnable;
|
||||
EndBitUnion(CTRL)
|
||||
|
||||
protected:
|
||||
std::string _name;
|
||||
|
||||
/** Pointer to parent class */
|
||||
Sp804 *parent;
|
||||
|
||||
/** Number of interrupt to cause/clear */
|
||||
uint32_t intNum;
|
||||
|
||||
/** Number of ticks in a clock input */
|
||||
Tick clock;
|
||||
|
||||
/** Control register as specified above */
|
||||
CTRL control;
|
||||
|
||||
/** If timer has caused an interrupt. This is irrespective of
|
||||
* interrupt enable */
|
||||
bool rawInt;
|
||||
|
||||
/** If an interrupt is currently pending. Logical and of CTRL.intEnable
|
||||
* and rawInt */
|
||||
bool pendingInt;
|
||||
|
||||
/** Value to load into counter when periodic mode reaches 0 */
|
||||
uint32_t loadValue;
|
||||
|
||||
/** Called when the counter reaches 0 */
|
||||
void counterAtZero();
|
||||
EventWrapper<Timer, &Timer::counterAtZero> zeroEvent;
|
||||
|
||||
public:
|
||||
/** Restart the counter ticking at val
|
||||
* @param val the value to start at (pre-16 bit masking if en) */
|
||||
void restartCounter(uint32_t val);
|
||||
|
||||
Timer(std::string __name, Sp804 *parent, int int_num, Tick clock);
|
||||
|
||||
std::string name() const { return _name; }
|
||||
|
||||
/** Handle read for a single timer */
|
||||
void read(PacketPtr pkt, Addr daddr);
|
||||
|
||||
/** Handle write for a single timer */
|
||||
void write(PacketPtr pkt, Addr daddr);
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
};
|
||||
|
||||
/** Pointer to the GIC for causing an interrupt */
|
||||
Gic *gic;
|
||||
|
||||
/** Timers that do the actual work */
|
||||
Timer timer0;
|
||||
Timer timer1;
|
||||
|
||||
public:
|
||||
typedef Sp804Params Params;
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
/**
|
||||
* The constructor for RealView just registers itself with the MMU.
|
||||
* @param p params structure
|
||||
*/
|
||||
Sp804(Params *p);
|
||||
|
||||
/**
|
||||
* Handle a read to the device
|
||||
* @param pkt The memory request.
|
||||
* @param data Where to put the data.
|
||||
*/
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* All writes are simply ignored.
|
||||
* @param pkt The memory request.
|
||||
* @param data the data
|
||||
*/
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
|
||||
#endif // __DEV_ARM_SP804_HH__
|
||||
|
||||
72
simulators/gem5/src/dev/baddev.cc
Normal file
72
simulators/gem5/src/dev/baddev.cc
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* BadDevice implemenation
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "config/the_isa.hh"
|
||||
#include "dev/baddev.hh"
|
||||
#include "mem/port.hh"
|
||||
#include "params/BadDevice.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
BadDevice::BadDevice(Params *p)
|
||||
: BasicPioDevice(p), devname(p->devicename)
|
||||
{
|
||||
pioSize = 0x10;
|
||||
}
|
||||
|
||||
Tick
|
||||
BadDevice::read(PacketPtr pkt)
|
||||
{
|
||||
panic("Device %s not imlpmented\n", devname);
|
||||
M5_DUMMY_RETURN
|
||||
}
|
||||
|
||||
Tick
|
||||
BadDevice::write(PacketPtr pkt)
|
||||
{
|
||||
panic("Device %s not imlpmented\n", devname);
|
||||
M5_DUMMY_RETURN
|
||||
}
|
||||
|
||||
BadDevice *
|
||||
BadDeviceParams::create()
|
||||
{
|
||||
return new BadDevice(this);
|
||||
}
|
||||
76
simulators/gem5/src/dev/baddev.hh
Normal file
76
simulators/gem5/src/dev/baddev.hh
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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 devices just panics when touched. For example if you have a
|
||||
* kernel that touches the frame buffer which isn't allowed.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_BADDEV_HH__
|
||||
#define __DEV_BADDEV_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "params/BadDevice.hh"
|
||||
|
||||
/**
|
||||
* BadDevice
|
||||
* This device just panics when accessed. It is supposed to warn
|
||||
* the user that the kernel they are running has unsupported
|
||||
* options (i.e. frame buffer)
|
||||
*/
|
||||
class BadDevice : public BasicPioDevice
|
||||
{
|
||||
private:
|
||||
std::string devname;
|
||||
|
||||
public:
|
||||
typedef BadDeviceParams Params;
|
||||
|
||||
protected:
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor for the Baddev Class.
|
||||
* @param p object parameters
|
||||
* @param a base address of the write
|
||||
*/
|
||||
BadDevice(Params *p);
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
};
|
||||
|
||||
#endif // __DEV_BADDEV_HH__
|
||||
782
simulators/gem5/src/dev/copy_engine.cc
Normal file
782
simulators/gem5/src/dev/copy_engine.cc
Normal file
@ -0,0 +1,782 @@
|
||||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2008 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
|
||||
* Device model for Intel's I/O AT DMA copy engine.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/cp_annotate.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/DMACopyEngine.hh"
|
||||
#include "dev/copy_engine.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "params/CopyEngine.hh"
|
||||
#include "sim/stats.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
using namespace CopyEngineReg;
|
||||
|
||||
CopyEngine::CopyEngine(const Params *p)
|
||||
: PciDev(p)
|
||||
{
|
||||
// All Reg regs are initialized to 0 by default
|
||||
regs.chanCount = p->ChanCnt;
|
||||
regs.xferCap = findMsbSet(p->XferCap);
|
||||
regs.attnStatus = 0;
|
||||
|
||||
if (regs.chanCount > 64)
|
||||
fatal("CopyEngine interface doesn't support more than 64 DMA engines\n");
|
||||
|
||||
for (int x = 0; x < regs.chanCount; x++) {
|
||||
CopyEngineChannel *ch = new CopyEngineChannel(this, x);
|
||||
chan.push_back(ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CopyEngine::CopyEngineChannel::CopyEngineChannel(CopyEngine *_ce, int cid)
|
||||
: cePort(_ce, _ce->sys, _ce->params()->min_backoff_delay,
|
||||
_ce->params()->max_backoff_delay),
|
||||
ce(_ce), channelId(cid), busy(false), underReset(false),
|
||||
refreshNext(false), latBeforeBegin(ce->params()->latBeforeBegin),
|
||||
latAfterCompletion(ce->params()->latAfterCompletion),
|
||||
completionDataReg(0), nextState(Idle), drainEvent(NULL),
|
||||
fetchCompleteEvent(this), addrCompleteEvent(this),
|
||||
readCompleteEvent(this), writeCompleteEvent(this),
|
||||
statusCompleteEvent(this)
|
||||
|
||||
{
|
||||
cr.status.dma_transfer_status(3);
|
||||
cr.descChainAddr = 0;
|
||||
cr.completionAddr = 0;
|
||||
|
||||
curDmaDesc = new DmaDesc;
|
||||
memset(curDmaDesc, 0, sizeof(DmaDesc));
|
||||
copyBuffer = new uint8_t[ce->params()->XferCap];
|
||||
}
|
||||
|
||||
CopyEngine::~CopyEngine()
|
||||
{
|
||||
for (int x = 0; x < chan.size(); x++) {
|
||||
delete chan[x];
|
||||
}
|
||||
}
|
||||
|
||||
CopyEngine::CopyEngineChannel::~CopyEngineChannel()
|
||||
{
|
||||
delete curDmaDesc;
|
||||
delete [] copyBuffer;
|
||||
}
|
||||
|
||||
MasterPort &
|
||||
CopyEngine::getMasterPort(const std::string &if_name, int idx)
|
||||
{
|
||||
if (if_name != "dma") {
|
||||
// pass it along to our super class
|
||||
return PciDev::getMasterPort(if_name, idx);
|
||||
} else {
|
||||
if (idx >= static_cast<int>(chan.size())) {
|
||||
panic("CopyEngine::getMasterPort: unknown index %d\n", idx);
|
||||
}
|
||||
|
||||
return chan[idx]->getMasterPort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MasterPort &
|
||||
CopyEngine::CopyEngineChannel::getMasterPort()
|
||||
{
|
||||
return cePort;
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::recvCommand()
|
||||
{
|
||||
if (cr.command.start_dma()) {
|
||||
assert(!busy);
|
||||
cr.status.dma_transfer_status(0);
|
||||
nextState = DescriptorFetch;
|
||||
fetchAddress = cr.descChainAddr;
|
||||
if (ce->getState() == SimObject::Running)
|
||||
fetchDescriptor(cr.descChainAddr);
|
||||
} else if (cr.command.append_dma()) {
|
||||
if (!busy) {
|
||||
nextState = AddressFetch;
|
||||
if (ce->getState() == SimObject::Running)
|
||||
fetchNextAddr(lastDescriptorAddr);
|
||||
} else
|
||||
refreshNext = true;
|
||||
} else if (cr.command.reset_dma()) {
|
||||
if (busy)
|
||||
underReset = true;
|
||||
else {
|
||||
cr.status.dma_transfer_status(3);
|
||||
nextState = Idle;
|
||||
}
|
||||
} else if (cr.command.resume_dma() || cr.command.abort_dma() ||
|
||||
cr.command.suspend_dma())
|
||||
panic("Resume, Abort, and Suspend are not supported\n");
|
||||
cr.command(0);
|
||||
}
|
||||
|
||||
Tick
|
||||
CopyEngine::read(PacketPtr pkt)
|
||||
{
|
||||
int bar;
|
||||
Addr daddr;
|
||||
|
||||
if (!getBAR(pkt->getAddr(), bar, daddr))
|
||||
panic("Invalid PCI memory access to unmapped memory.\n");
|
||||
|
||||
// Only Memory register BAR is allowed
|
||||
assert(bar == 0);
|
||||
|
||||
int size = pkt->getSize();
|
||||
if (size != sizeof(uint64_t) && size != sizeof(uint32_t) &&
|
||||
size != sizeof(uint16_t) && size != sizeof(uint8_t)) {
|
||||
panic("Unknown size for MMIO access: %d\n", pkt->getSize());
|
||||
}
|
||||
|
||||
DPRINTF(DMACopyEngine, "Read device register %#X size: %d\n", daddr, size);
|
||||
|
||||
pkt->allocate();
|
||||
|
||||
///
|
||||
/// Handle read of register here
|
||||
///
|
||||
|
||||
if (daddr < 0x80) {
|
||||
switch (daddr) {
|
||||
case GEN_CHANCOUNT:
|
||||
assert(size == sizeof(regs.chanCount));
|
||||
pkt->set<uint8_t>(regs.chanCount);
|
||||
break;
|
||||
case GEN_XFERCAP:
|
||||
assert(size == sizeof(regs.xferCap));
|
||||
pkt->set<uint8_t>(regs.xferCap);
|
||||
break;
|
||||
case GEN_INTRCTRL:
|
||||
assert(size == sizeof(uint8_t));
|
||||
pkt->set<uint8_t>(regs.intrctrl());
|
||||
regs.intrctrl.master_int_enable(0);
|
||||
break;
|
||||
case GEN_ATTNSTATUS:
|
||||
assert(size == sizeof(regs.attnStatus));
|
||||
pkt->set<uint32_t>(regs.attnStatus);
|
||||
regs.attnStatus = 0;
|
||||
break;
|
||||
default:
|
||||
panic("Read request to unknown register number: %#x\n", daddr);
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
|
||||
// Find which channel we're accessing
|
||||
int chanid = 0;
|
||||
daddr -= 0x80;
|
||||
while (daddr >= 0x80) {
|
||||
chanid++;
|
||||
daddr -= 0x80;
|
||||
}
|
||||
|
||||
if (chanid >= regs.chanCount)
|
||||
panic("Access to channel %d (device only configured for %d channels)",
|
||||
chanid, regs.chanCount);
|
||||
|
||||
///
|
||||
/// Channel registers are handled here
|
||||
///
|
||||
chan[chanid]->channelRead(pkt, daddr, size);
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::channelRead(Packet *pkt, Addr daddr, int size)
|
||||
{
|
||||
switch (daddr) {
|
||||
case CHAN_CONTROL:
|
||||
assert(size == sizeof(uint16_t));
|
||||
pkt->set<uint16_t>(cr.ctrl());
|
||||
cr.ctrl.in_use(1);
|
||||
break;
|
||||
case CHAN_STATUS:
|
||||
assert(size == sizeof(uint64_t));
|
||||
pkt->set<uint64_t>(cr.status() | ~busy);
|
||||
break;
|
||||
case CHAN_CHAINADDR:
|
||||
assert(size == sizeof(uint64_t) || size == sizeof(uint32_t));
|
||||
if (size == sizeof(uint64_t))
|
||||
pkt->set<uint64_t>(cr.descChainAddr);
|
||||
else
|
||||
pkt->set<uint32_t>(bits(cr.descChainAddr,0,31));
|
||||
break;
|
||||
case CHAN_CHAINADDR_HIGH:
|
||||
assert(size == sizeof(uint32_t));
|
||||
pkt->set<uint32_t>(bits(cr.descChainAddr,32,63));
|
||||
break;
|
||||
case CHAN_COMMAND:
|
||||
assert(size == sizeof(uint8_t));
|
||||
pkt->set<uint32_t>(cr.command());
|
||||
break;
|
||||
case CHAN_CMPLNADDR:
|
||||
assert(size == sizeof(uint64_t) || size == sizeof(uint32_t));
|
||||
if (size == sizeof(uint64_t))
|
||||
pkt->set<uint64_t>(cr.completionAddr);
|
||||
else
|
||||
pkt->set<uint32_t>(bits(cr.completionAddr,0,31));
|
||||
break;
|
||||
case CHAN_CMPLNADDR_HIGH:
|
||||
assert(size == sizeof(uint32_t));
|
||||
pkt->set<uint32_t>(bits(cr.completionAddr,32,63));
|
||||
break;
|
||||
case CHAN_ERROR:
|
||||
assert(size == sizeof(uint32_t));
|
||||
pkt->set<uint32_t>(cr.error());
|
||||
break;
|
||||
default:
|
||||
panic("Read request to unknown channel register number: (%d)%#x\n",
|
||||
channelId, daddr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Tick
|
||||
CopyEngine::write(PacketPtr pkt)
|
||||
{
|
||||
int bar;
|
||||
Addr daddr;
|
||||
|
||||
|
||||
if (!getBAR(pkt->getAddr(), bar, daddr))
|
||||
panic("Invalid PCI memory access to unmapped memory.\n");
|
||||
|
||||
// Only Memory register BAR is allowed
|
||||
assert(bar == 0);
|
||||
|
||||
int size = pkt->getSize();
|
||||
|
||||
///
|
||||
/// Handle write of register here
|
||||
///
|
||||
|
||||
if (size == sizeof(uint64_t)) {
|
||||
uint64_t val M5_VAR_USED = pkt->get<uint64_t>();
|
||||
DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val);
|
||||
} else if (size == sizeof(uint32_t)) {
|
||||
uint32_t val M5_VAR_USED = pkt->get<uint32_t>();
|
||||
DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val);
|
||||
} else if (size == sizeof(uint16_t)) {
|
||||
uint16_t val M5_VAR_USED = pkt->get<uint16_t>();
|
||||
DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val);
|
||||
} else if (size == sizeof(uint8_t)) {
|
||||
uint8_t val M5_VAR_USED = pkt->get<uint8_t>();
|
||||
DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val);
|
||||
} else {
|
||||
panic("Unknown size for MMIO access: %d\n", size);
|
||||
}
|
||||
|
||||
if (daddr < 0x80) {
|
||||
switch (daddr) {
|
||||
case GEN_CHANCOUNT:
|
||||
case GEN_XFERCAP:
|
||||
case GEN_ATTNSTATUS:
|
||||
DPRINTF(DMACopyEngine, "Warning, ignorning write to register %x\n",
|
||||
daddr);
|
||||
break;
|
||||
case GEN_INTRCTRL:
|
||||
regs.intrctrl.master_int_enable(bits(pkt->get<uint8_t>(),0,1));
|
||||
break;
|
||||
default:
|
||||
panic("Read request to unknown register number: %#x\n", daddr);
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
// Find which channel we're accessing
|
||||
int chanid = 0;
|
||||
daddr -= 0x80;
|
||||
while (daddr >= 0x80) {
|
||||
chanid++;
|
||||
daddr -= 0x80;
|
||||
}
|
||||
|
||||
if (chanid >= regs.chanCount)
|
||||
panic("Access to channel %d (device only configured for %d channels)",
|
||||
chanid, regs.chanCount);
|
||||
|
||||
///
|
||||
/// Channel registers are handled here
|
||||
///
|
||||
chan[chanid]->channelWrite(pkt, daddr, size);
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::channelWrite(Packet *pkt, Addr daddr, int size)
|
||||
{
|
||||
switch (daddr) {
|
||||
case CHAN_CONTROL:
|
||||
assert(size == sizeof(uint16_t));
|
||||
int old_int_disable;
|
||||
old_int_disable = cr.ctrl.interrupt_disable();
|
||||
cr.ctrl(pkt->get<uint16_t>());
|
||||
if (cr.ctrl.interrupt_disable())
|
||||
cr.ctrl.interrupt_disable(0);
|
||||
else
|
||||
cr.ctrl.interrupt_disable(old_int_disable);
|
||||
break;
|
||||
case CHAN_STATUS:
|
||||
assert(size == sizeof(uint64_t));
|
||||
DPRINTF(DMACopyEngine, "Warning, ignorning write to register %x\n",
|
||||
daddr);
|
||||
break;
|
||||
case CHAN_CHAINADDR:
|
||||
assert(size == sizeof(uint64_t) || size == sizeof(uint32_t));
|
||||
if (size == sizeof(uint64_t))
|
||||
cr.descChainAddr = pkt->get<uint64_t>();
|
||||
else
|
||||
cr.descChainAddr = (uint64_t)pkt->get<uint32_t>() |
|
||||
(cr.descChainAddr & ~mask(32));
|
||||
DPRINTF(DMACopyEngine, "Chain Address %x\n", cr.descChainAddr);
|
||||
break;
|
||||
case CHAN_CHAINADDR_HIGH:
|
||||
assert(size == sizeof(uint32_t));
|
||||
cr.descChainAddr = ((uint64_t)pkt->get<uint32_t>() <<32) |
|
||||
(cr.descChainAddr & mask(32));
|
||||
DPRINTF(DMACopyEngine, "Chain Address %x\n", cr.descChainAddr);
|
||||
break;
|
||||
case CHAN_COMMAND:
|
||||
assert(size == sizeof(uint8_t));
|
||||
cr.command(pkt->get<uint8_t>());
|
||||
recvCommand();
|
||||
break;
|
||||
case CHAN_CMPLNADDR:
|
||||
assert(size == sizeof(uint64_t) || size == sizeof(uint32_t));
|
||||
if (size == sizeof(uint64_t))
|
||||
cr.completionAddr = pkt->get<uint64_t>();
|
||||
else
|
||||
cr.completionAddr = pkt->get<uint32_t>() |
|
||||
(cr.completionAddr & ~mask(32));
|
||||
break;
|
||||
case CHAN_CMPLNADDR_HIGH:
|
||||
assert(size == sizeof(uint32_t));
|
||||
cr.completionAddr = ((uint64_t)pkt->get<uint32_t>() <<32) |
|
||||
(cr.completionAddr & mask(32));
|
||||
break;
|
||||
case CHAN_ERROR:
|
||||
assert(size == sizeof(uint32_t));
|
||||
cr.error(~pkt->get<uint32_t>() & cr.error());
|
||||
break;
|
||||
default:
|
||||
panic("Read request to unknown channel register number: (%d)%#x\n",
|
||||
channelId, daddr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::regStats()
|
||||
{
|
||||
using namespace Stats;
|
||||
bytesCopied
|
||||
.init(regs.chanCount)
|
||||
.name(name() + ".bytes_copied")
|
||||
.desc("Number of bytes copied by each engine")
|
||||
.flags(total)
|
||||
;
|
||||
copiesProcessed
|
||||
.init(regs.chanCount)
|
||||
.name(name() + ".copies_processed")
|
||||
.desc("Number of copies processed by each engine")
|
||||
.flags(total)
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::fetchDescriptor(Addr address)
|
||||
{
|
||||
anDq();
|
||||
anBegin("FetchDescriptor");
|
||||
DPRINTF(DMACopyEngine, "Reading descriptor from at memory location %#x(%#x)\n",
|
||||
address, ce->platform->pciToDma(address));
|
||||
assert(address);
|
||||
busy = true;
|
||||
|
||||
DPRINTF(DMACopyEngine, "dmaAction: %#x, %d bytes, to addr %#x\n",
|
||||
ce->platform->pciToDma(address), sizeof(DmaDesc), curDmaDesc);
|
||||
|
||||
cePort.dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address),
|
||||
sizeof(DmaDesc), &fetchCompleteEvent,
|
||||
(uint8_t*)curDmaDesc, latBeforeBegin);
|
||||
lastDescriptorAddr = address;
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::fetchDescComplete()
|
||||
{
|
||||
DPRINTF(DMACopyEngine, "Read of descriptor complete\n");
|
||||
|
||||
if ((curDmaDesc->command & DESC_CTRL_NULL)) {
|
||||
DPRINTF(DMACopyEngine, "Got NULL descriptor, skipping\n");
|
||||
assert(!(curDmaDesc->command & DESC_CTRL_CP_STS));
|
||||
if (curDmaDesc->command & DESC_CTRL_CP_STS) {
|
||||
panic("Shouldn't be able to get here\n");
|
||||
nextState = CompletionWrite;
|
||||
if (inDrain()) return;
|
||||
writeCompletionStatus();
|
||||
} else {
|
||||
anBegin("Idle");
|
||||
anWait();
|
||||
busy = false;
|
||||
nextState = Idle;
|
||||
inDrain();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (curDmaDesc->command & ~DESC_CTRL_CP_STS)
|
||||
panic("Descriptor has flag other that completion status set\n");
|
||||
|
||||
nextState = DMARead;
|
||||
if (inDrain()) return;
|
||||
readCopyBytes();
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::readCopyBytes()
|
||||
{
|
||||
anBegin("ReadCopyBytes");
|
||||
DPRINTF(DMACopyEngine, "Reading %d bytes from buffer to memory location %#x(%#x)\n",
|
||||
curDmaDesc->len, curDmaDesc->dest,
|
||||
ce->platform->pciToDma(curDmaDesc->src));
|
||||
cePort.dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(curDmaDesc->src),
|
||||
curDmaDesc->len, &readCompleteEvent, copyBuffer, 0);
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::readCopyBytesComplete()
|
||||
{
|
||||
DPRINTF(DMACopyEngine, "Read of bytes to copy complete\n");
|
||||
|
||||
nextState = DMAWrite;
|
||||
if (inDrain()) return;
|
||||
writeCopyBytes();
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::writeCopyBytes()
|
||||
{
|
||||
anBegin("WriteCopyBytes");
|
||||
DPRINTF(DMACopyEngine, "Writing %d bytes from buffer to memory location %#x(%#x)\n",
|
||||
curDmaDesc->len, curDmaDesc->dest,
|
||||
ce->platform->pciToDma(curDmaDesc->dest));
|
||||
|
||||
cePort.dmaAction(MemCmd::WriteReq, ce->platform->pciToDma(curDmaDesc->dest),
|
||||
curDmaDesc->len, &writeCompleteEvent, copyBuffer, 0);
|
||||
|
||||
ce->bytesCopied[channelId] += curDmaDesc->len;
|
||||
ce->copiesProcessed[channelId]++;
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::writeCopyBytesComplete()
|
||||
{
|
||||
DPRINTF(DMACopyEngine, "Write of bytes to copy complete user1: %#x\n",
|
||||
curDmaDesc->user1);
|
||||
|
||||
cr.status.compl_desc_addr(lastDescriptorAddr >> 6);
|
||||
completionDataReg = cr.status() | 1;
|
||||
|
||||
anQ("DMAUsedDescQ", channelId, 1);
|
||||
anQ("AppRecvQ", curDmaDesc->user1, curDmaDesc->len);
|
||||
if (curDmaDesc->command & DESC_CTRL_CP_STS) {
|
||||
nextState = CompletionWrite;
|
||||
if (inDrain()) return;
|
||||
writeCompletionStatus();
|
||||
return;
|
||||
}
|
||||
|
||||
continueProcessing();
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::continueProcessing()
|
||||
{
|
||||
busy = false;
|
||||
|
||||
if (underReset) {
|
||||
anBegin("Reset");
|
||||
anWait();
|
||||
underReset = false;
|
||||
refreshNext = false;
|
||||
busy = false;
|
||||
nextState = Idle;
|
||||
return;
|
||||
}
|
||||
|
||||
if (curDmaDesc->next) {
|
||||
nextState = DescriptorFetch;
|
||||
fetchAddress = curDmaDesc->next;
|
||||
if (inDrain()) return;
|
||||
fetchDescriptor(curDmaDesc->next);
|
||||
} else if (refreshNext) {
|
||||
nextState = AddressFetch;
|
||||
refreshNext = false;
|
||||
if (inDrain()) return;
|
||||
fetchNextAddr(lastDescriptorAddr);
|
||||
} else {
|
||||
inDrain();
|
||||
nextState = Idle;
|
||||
anWait();
|
||||
anBegin("Idle");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::writeCompletionStatus()
|
||||
{
|
||||
anBegin("WriteCompletionStatus");
|
||||
DPRINTF(DMACopyEngine, "Writing completion status %#x to address %#x(%#x)\n",
|
||||
completionDataReg, cr.completionAddr,
|
||||
ce->platform->pciToDma(cr.completionAddr));
|
||||
|
||||
cePort.dmaAction(MemCmd::WriteReq,
|
||||
ce->platform->pciToDma(cr.completionAddr),
|
||||
sizeof(completionDataReg), &statusCompleteEvent,
|
||||
(uint8_t*)&completionDataReg, latAfterCompletion);
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::writeStatusComplete()
|
||||
{
|
||||
DPRINTF(DMACopyEngine, "Writing completion status complete\n");
|
||||
continueProcessing();
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::fetchNextAddr(Addr address)
|
||||
{
|
||||
anBegin("FetchNextAddr");
|
||||
DPRINTF(DMACopyEngine, "Fetching next address...\n");
|
||||
busy = true;
|
||||
cePort.dmaAction(MemCmd::ReadReq,
|
||||
ce->platform->pciToDma(address + offsetof(DmaDesc, next)),
|
||||
sizeof(Addr), &addrCompleteEvent,
|
||||
(uint8_t*)curDmaDesc + offsetof(DmaDesc, next), 0);
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::fetchAddrComplete()
|
||||
{
|
||||
DPRINTF(DMACopyEngine, "Fetching next address complete: %#x\n",
|
||||
curDmaDesc->next);
|
||||
if (!curDmaDesc->next) {
|
||||
DPRINTF(DMACopyEngine, "Got NULL descriptor, nothing more to do\n");
|
||||
busy = false;
|
||||
nextState = Idle;
|
||||
anWait();
|
||||
anBegin("Idle");
|
||||
inDrain();
|
||||
return;
|
||||
}
|
||||
nextState = DescriptorFetch;
|
||||
fetchAddress = curDmaDesc->next;
|
||||
if (inDrain()) return;
|
||||
fetchDescriptor(curDmaDesc->next);
|
||||
}
|
||||
|
||||
bool
|
||||
CopyEngine::CopyEngineChannel::inDrain()
|
||||
{
|
||||
if (ce->getState() == SimObject::Draining) {
|
||||
DPRINTF(DMACopyEngine, "processing drain\n");
|
||||
assert(drainEvent);
|
||||
drainEvent->process();
|
||||
drainEvent = NULL;
|
||||
}
|
||||
|
||||
return ce->getState() != SimObject::Running;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
CopyEngine::CopyEngineChannel::drain(Event *de)
|
||||
{
|
||||
if (nextState == Idle || ce->getState() != SimObject::Running)
|
||||
return 0;
|
||||
unsigned int count = 1;
|
||||
count += cePort.drain(de);
|
||||
|
||||
DPRINTF(DMACopyEngine, "unable to drain, returning %d\n", count);
|
||||
drainEvent = de;
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
CopyEngine::drain(Event *de)
|
||||
{
|
||||
unsigned int count;
|
||||
count = pioPort.drain(de) + dmaPort.drain(de) + configPort.drain(de);
|
||||
for (int x = 0;x < chan.size(); x++)
|
||||
count += chan[x]->drain(de);
|
||||
|
||||
if (count)
|
||||
changeState(Draining);
|
||||
else
|
||||
changeState(Drained);
|
||||
|
||||
DPRINTF(DMACopyEngine, "call to CopyEngine::drain() returning %d\n", count);
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::serialize(std::ostream &os)
|
||||
{
|
||||
PciDev::serialize(os);
|
||||
regs.serialize(os);
|
||||
for (int x =0; x < chan.size(); x++) {
|
||||
nameOut(os, csprintf("%s.channel%d", name(), x));
|
||||
chan[x]->serialize(os);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
PciDev::unserialize(cp, section);
|
||||
regs.unserialize(cp, section);
|
||||
for (int x = 0; x < chan.size(); x++)
|
||||
chan[x]->unserialize(cp, csprintf("%s.channel%d", section, x));
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(channelId);
|
||||
SERIALIZE_SCALAR(busy);
|
||||
SERIALIZE_SCALAR(underReset);
|
||||
SERIALIZE_SCALAR(refreshNext);
|
||||
SERIALIZE_SCALAR(lastDescriptorAddr);
|
||||
SERIALIZE_SCALAR(completionDataReg);
|
||||
SERIALIZE_SCALAR(fetchAddress);
|
||||
int nextState = this->nextState;
|
||||
SERIALIZE_SCALAR(nextState);
|
||||
arrayParamOut(os, "curDmaDesc", (uint8_t*)curDmaDesc, sizeof(DmaDesc));
|
||||
SERIALIZE_ARRAY(copyBuffer, ce->params()->XferCap);
|
||||
cr.serialize(os);
|
||||
|
||||
}
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(channelId);
|
||||
UNSERIALIZE_SCALAR(busy);
|
||||
UNSERIALIZE_SCALAR(underReset);
|
||||
UNSERIALIZE_SCALAR(refreshNext);
|
||||
UNSERIALIZE_SCALAR(lastDescriptorAddr);
|
||||
UNSERIALIZE_SCALAR(completionDataReg);
|
||||
UNSERIALIZE_SCALAR(fetchAddress);
|
||||
int nextState;
|
||||
UNSERIALIZE_SCALAR(nextState);
|
||||
this->nextState = (ChannelState)nextState;
|
||||
arrayParamIn(cp, section, "curDmaDesc", (uint8_t*)curDmaDesc, sizeof(DmaDesc));
|
||||
UNSERIALIZE_ARRAY(copyBuffer, ce->params()->XferCap);
|
||||
cr.unserialize(cp, section);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::restartStateMachine()
|
||||
{
|
||||
switch(nextState) {
|
||||
case AddressFetch:
|
||||
fetchNextAddr(lastDescriptorAddr);
|
||||
break;
|
||||
case DescriptorFetch:
|
||||
fetchDescriptor(fetchAddress);
|
||||
break;
|
||||
case DMARead:
|
||||
readCopyBytes();
|
||||
break;
|
||||
case DMAWrite:
|
||||
writeCopyBytes();
|
||||
break;
|
||||
case CompletionWrite:
|
||||
writeCompletionStatus();
|
||||
break;
|
||||
case Idle:
|
||||
break;
|
||||
default:
|
||||
panic("Unknown state for CopyEngineChannel\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::resume()
|
||||
{
|
||||
SimObject::resume();
|
||||
for (int x = 0;x < chan.size(); x++)
|
||||
chan[x]->resume();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::resume()
|
||||
{
|
||||
DPRINTF(DMACopyEngine, "Restarting state machine at state %d\n", nextState);
|
||||
restartStateMachine();
|
||||
}
|
||||
|
||||
CopyEngine *
|
||||
CopyEngineParams::create()
|
||||
{
|
||||
return new CopyEngine(this);
|
||||
}
|
||||
212
simulators/gem5/src/dev/copy_engine.hh
Normal file
212
simulators/gem5/src/dev/copy_engine.hh
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2008 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
|
||||
* Device model for Intel's I/O Acceleration Technology (I/OAT).
|
||||
* A DMA asyncronous copy engine
|
||||
*/
|
||||
|
||||
#ifndef __DEV_COPY_ENGINE_HH__
|
||||
#define __DEV_COPY_ENGINE_HH__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/statistics.hh"
|
||||
#include "dev/copy_engine_defs.hh"
|
||||
#include "dev/pcidev.hh"
|
||||
#include "params/CopyEngine.hh"
|
||||
#include "sim/eventq.hh"
|
||||
|
||||
class CopyEngine : public PciDev
|
||||
{
|
||||
class CopyEngineChannel
|
||||
{
|
||||
private:
|
||||
DmaPort cePort;
|
||||
CopyEngine *ce;
|
||||
CopyEngineReg::ChanRegs cr;
|
||||
int channelId;
|
||||
CopyEngineReg::DmaDesc *curDmaDesc;
|
||||
uint8_t *copyBuffer;
|
||||
|
||||
bool busy;
|
||||
bool underReset;
|
||||
bool refreshNext;
|
||||
Addr lastDescriptorAddr;
|
||||
Addr fetchAddress;
|
||||
|
||||
Tick latBeforeBegin;
|
||||
Tick latAfterCompletion;
|
||||
|
||||
uint64_t completionDataReg;
|
||||
|
||||
enum ChannelState {
|
||||
Idle,
|
||||
AddressFetch,
|
||||
DescriptorFetch,
|
||||
DMARead,
|
||||
DMAWrite,
|
||||
CompletionWrite
|
||||
};
|
||||
|
||||
ChannelState nextState;
|
||||
|
||||
Event *drainEvent;
|
||||
public:
|
||||
CopyEngineChannel(CopyEngine *_ce, int cid);
|
||||
virtual ~CopyEngineChannel();
|
||||
MasterPort &getMasterPort();
|
||||
|
||||
std::string name() { assert(ce); return ce->name() + csprintf("-chan%d", channelId); }
|
||||
virtual Tick read(PacketPtr pkt)
|
||||
{ panic("CopyEngineChannel has no I/O access\n");}
|
||||
virtual Tick write(PacketPtr pkt)
|
||||
{ panic("CopyEngineChannel has no I/O access\n"); }
|
||||
|
||||
void channelRead(PacketPtr pkt, Addr daddr, int size);
|
||||
void channelWrite(PacketPtr pkt, Addr daddr, int size);
|
||||
|
||||
unsigned int drain(Event *de);
|
||||
void resume();
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
private:
|
||||
void fetchDescriptor(Addr address);
|
||||
void fetchDescComplete();
|
||||
EventWrapper<CopyEngineChannel, &CopyEngineChannel::fetchDescComplete>
|
||||
fetchCompleteEvent;
|
||||
|
||||
void fetchNextAddr(Addr address);
|
||||
void fetchAddrComplete();
|
||||
EventWrapper<CopyEngineChannel, &CopyEngineChannel::fetchAddrComplete>
|
||||
addrCompleteEvent;
|
||||
|
||||
void readCopyBytes();
|
||||
void readCopyBytesComplete();
|
||||
EventWrapper<CopyEngineChannel, &CopyEngineChannel::readCopyBytesComplete>
|
||||
readCompleteEvent;
|
||||
|
||||
void writeCopyBytes();
|
||||
void writeCopyBytesComplete();
|
||||
EventWrapper <CopyEngineChannel, &CopyEngineChannel::writeCopyBytesComplete>
|
||||
writeCompleteEvent;
|
||||
|
||||
void writeCompletionStatus();
|
||||
void writeStatusComplete();
|
||||
EventWrapper <CopyEngineChannel, &CopyEngineChannel::writeStatusComplete>
|
||||
statusCompleteEvent;
|
||||
|
||||
|
||||
void continueProcessing();
|
||||
void recvCommand();
|
||||
bool inDrain();
|
||||
void restartStateMachine();
|
||||
inline void anBegin(const char *s)
|
||||
{
|
||||
CPA::cpa()->hwBegin(CPA::FL_NONE, ce->sys,
|
||||
channelId, "CopyEngine", s);
|
||||
}
|
||||
|
||||
inline void anWait()
|
||||
{
|
||||
CPA::cpa()->hwWe(CPA::FL_NONE, ce->sys,
|
||||
channelId, "CopyEngine", "DMAUnusedDescQ", channelId);
|
||||
}
|
||||
|
||||
inline void anDq()
|
||||
{
|
||||
CPA::cpa()->hwDq(CPA::FL_NONE, ce->sys,
|
||||
channelId, "CopyEngine", "DMAUnusedDescQ", channelId);
|
||||
}
|
||||
|
||||
inline void anPq()
|
||||
{
|
||||
CPA::cpa()->hwDq(CPA::FL_NONE, ce->sys,
|
||||
channelId, "CopyEngine", "DMAUnusedDescQ", channelId);
|
||||
}
|
||||
|
||||
inline void anQ(const char * s, uint64_t id, int size = 1)
|
||||
{
|
||||
CPA::cpa()->hwQ(CPA::FL_NONE, ce->sys, channelId,
|
||||
"CopyEngine", s, id, NULL, size);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Stats::Vector bytesCopied;
|
||||
Stats::Vector copiesProcessed;
|
||||
|
||||
// device registers
|
||||
CopyEngineReg::Regs regs;
|
||||
|
||||
// Array of channels each one with regs/dma port/etc
|
||||
std::vector<CopyEngineChannel*> chan;
|
||||
|
||||
public:
|
||||
typedef CopyEngineParams Params;
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
CopyEngine(const Params *params);
|
||||
~CopyEngine();
|
||||
|
||||
void regStats();
|
||||
|
||||
virtual MasterPort &getMasterPort(const std::string &if_name,
|
||||
int idx = -1);
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
virtual unsigned int drain(Event *de);
|
||||
virtual void resume();
|
||||
};
|
||||
|
||||
#endif //__DEV_COPY_ENGINE_HH__
|
||||
|
||||
225
simulators/gem5/src/dev/copy_engine_defs.hh
Normal file
225
simulators/gem5/src/dev/copy_engine_defs.hh
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright (c) 2008 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
|
||||
* Register and structure descriptions for Intel's I/O AT DMA Engine
|
||||
*/
|
||||
#include "base/bitfield.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
namespace CopyEngineReg {
|
||||
|
||||
|
||||
// General Channel independant registers, 128 bytes starting at 0x00
|
||||
const uint32_t GEN_CHANCOUNT = 0x00;
|
||||
const uint32_t GEN_XFERCAP = 0x01;
|
||||
const uint32_t GEN_INTRCTRL = 0x03;
|
||||
const uint32_t GEN_ATTNSTATUS = 0x04;
|
||||
|
||||
|
||||
// Channel specific registers, each block is 128 bytes, starting at 0x80
|
||||
const uint32_t CHAN_CONTROL = 0x00;
|
||||
const uint32_t CHAN_STATUS = 0x04;
|
||||
const uint32_t CHAN_CHAINADDR = 0x0C;
|
||||
const uint32_t CHAN_CHAINADDR_LOW = 0x0C;
|
||||
const uint32_t CHAN_CHAINADDR_HIGH = 0x10;
|
||||
const uint32_t CHAN_COMMAND = 0x14;
|
||||
const uint32_t CHAN_CMPLNADDR = 0x18;
|
||||
const uint32_t CHAN_CMPLNADDR_LOW = 0x18;
|
||||
const uint32_t CHAN_CMPLNADDR_HIGH = 0x1C;
|
||||
const uint32_t CHAN_ERROR = 0x28;
|
||||
|
||||
|
||||
const uint32_t DESC_CTRL_INT_GEN = 0x00000001;
|
||||
const uint32_t DESC_CTRL_SRC_SN = 0x00000002;
|
||||
const uint32_t DESC_CTRL_DST_SN = 0x00000004;
|
||||
const uint32_t DESC_CTRL_CP_STS = 0x00000008;
|
||||
const uint32_t DESC_CTRL_FRAME = 0x00000010;
|
||||
const uint32_t DESC_CTRL_NULL = 0x00000020;
|
||||
|
||||
struct DmaDesc {
|
||||
uint32_t len;
|
||||
uint32_t command;
|
||||
Addr src;
|
||||
Addr dest;
|
||||
Addr next;
|
||||
uint64_t reserved1;
|
||||
uint64_t reserved2;
|
||||
uint64_t user1;
|
||||
uint64_t user2;
|
||||
};
|
||||
|
||||
#define ADD_FIELD8(NAME, OFFSET, BITS) \
|
||||
inline uint8_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \
|
||||
inline void NAME(uint8_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); }
|
||||
|
||||
#define ADD_FIELD16(NAME, OFFSET, BITS) \
|
||||
inline uint16_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \
|
||||
inline void NAME(uint16_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); }
|
||||
|
||||
#define ADD_FIELD32(NAME, OFFSET, BITS) \
|
||||
inline uint32_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \
|
||||
inline void NAME(uint32_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); }
|
||||
|
||||
#define ADD_FIELD64(NAME, OFFSET, BITS) \
|
||||
inline uint64_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \
|
||||
inline void NAME(uint64_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); }
|
||||
|
||||
template<class T>
|
||||
struct Reg {
|
||||
T _data;
|
||||
T operator()() { return _data; }
|
||||
const Reg<T> &operator=(T d) { _data = d; return *this;}
|
||||
bool operator==(T d) { return d == _data; }
|
||||
void operator()(T d) { _data = d; }
|
||||
Reg() { _data = 0; }
|
||||
void serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(_data);
|
||||
}
|
||||
void unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(_data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Regs {
|
||||
uint8_t chanCount;
|
||||
uint8_t xferCap;
|
||||
|
||||
struct INTRCTRL : public Reg<uint8_t> { // 0x03
|
||||
using Reg<uint8_t>::operator =;
|
||||
ADD_FIELD8(master_int_enable,0,1);
|
||||
ADD_FIELD8(interrupt_status,1,1);
|
||||
ADD_FIELD8(interrupt,2,1);
|
||||
};
|
||||
INTRCTRL intrctrl;
|
||||
|
||||
uint32_t attnStatus; // Read clears
|
||||
|
||||
void serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(chanCount);
|
||||
SERIALIZE_SCALAR(xferCap);
|
||||
paramOut(os, "intrctrl", intrctrl._data);
|
||||
SERIALIZE_SCALAR(attnStatus);
|
||||
}
|
||||
|
||||
void unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(chanCount);
|
||||
UNSERIALIZE_SCALAR(xferCap);
|
||||
paramIn(cp, section, "intrctrl", intrctrl._data);
|
||||
UNSERIALIZE_SCALAR(attnStatus);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct ChanRegs {
|
||||
struct CHANCTRL : public Reg<uint16_t> { // channelX + 0x00
|
||||
using Reg<uint16_t>::operator =;
|
||||
ADD_FIELD16(interrupt_disable,0,1);
|
||||
ADD_FIELD16(error_completion_enable, 2,1);
|
||||
ADD_FIELD16(any_error_abort_enable,3,1);
|
||||
ADD_FIELD16(error_int_enable,4,1);
|
||||
ADD_FIELD16(desc_addr_snoop_control,5,1);
|
||||
ADD_FIELD16(in_use, 8,1);
|
||||
};
|
||||
CHANCTRL ctrl;
|
||||
|
||||
struct CHANSTS : public Reg<uint64_t> { // channelX + 0x04
|
||||
ADD_FIELD64(dma_transfer_status, 0, 3);
|
||||
ADD_FIELD64(unaffiliated_error, 3, 1);
|
||||
ADD_FIELD64(soft_error, 4, 1);
|
||||
ADD_FIELD64(compl_desc_addr, 6, 58);
|
||||
};
|
||||
CHANSTS status;
|
||||
|
||||
uint64_t descChainAddr;
|
||||
|
||||
struct CHANCMD : public Reg<uint8_t> { // channelX + 0x14
|
||||
ADD_FIELD8(start_dma,0,1);
|
||||
ADD_FIELD8(append_dma,1,1);
|
||||
ADD_FIELD8(suspend_dma,2,1);
|
||||
ADD_FIELD8(abort_dma,3,1);
|
||||
ADD_FIELD8(resume_dma,4,1);
|
||||
ADD_FIELD8(reset_dma,5,1);
|
||||
};
|
||||
CHANCMD command;
|
||||
|
||||
uint64_t completionAddr;
|
||||
|
||||
struct CHANERR : public Reg<uint32_t> { // channel X + 0x28
|
||||
ADD_FIELD32(source_addr_error,0,1);
|
||||
ADD_FIELD32(dest_addr_error,1,1);
|
||||
ADD_FIELD32(ndesc_addr_error,2,1);
|
||||
ADD_FIELD32(desc_error,3,1);
|
||||
ADD_FIELD32(chain_addr_error,4,1);
|
||||
ADD_FIELD32(chain_cmd_error,5,1);
|
||||
ADD_FIELD32(chipset_parity_error,6,1);
|
||||
ADD_FIELD32(dma_parity_error,7,1);
|
||||
ADD_FIELD32(read_data_error,8,1);
|
||||
ADD_FIELD32(write_data_error,9,1);
|
||||
ADD_FIELD32(desc_control_error,10,1);
|
||||
ADD_FIELD32(desc_len_error,11,1);
|
||||
ADD_FIELD32(completion_addr_error,12,1);
|
||||
ADD_FIELD32(interrupt_config_error,13,1);
|
||||
ADD_FIELD32(soft_error,14,1);
|
||||
ADD_FIELD32(unaffiliated_error,15,1);
|
||||
};
|
||||
CHANERR error;
|
||||
|
||||
void serialize(std::ostream &os)
|
||||
{
|
||||
paramOut(os, "ctrl", ctrl._data);
|
||||
paramOut(os, "status", status._data);
|
||||
SERIALIZE_SCALAR(descChainAddr);
|
||||
paramOut(os, "command", command._data);
|
||||
SERIALIZE_SCALAR(completionAddr);
|
||||
paramOut(os, "error", error._data);
|
||||
}
|
||||
|
||||
void unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
paramIn(cp, section, "ctrl", ctrl._data);
|
||||
paramIn(cp, section, "status", status._data);
|
||||
UNSERIALIZE_SCALAR(descChainAddr);
|
||||
paramIn(cp, section, "command", command._data);
|
||||
UNSERIALIZE_SCALAR(completionAddr);
|
||||
paramIn(cp, section, "error", error._data);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace CopyEngineReg
|
||||
|
||||
|
||||
429
simulators/gem5/src/dev/disk_image.cc
Normal file
429
simulators/gem5/src/dev/disk_image.cc
Normal file
@ -0,0 +1,429 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Disk Image Definitions
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "base/callback.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/DiskImageRead.hh"
|
||||
#include "debug/DiskImageWrite.hh"
|
||||
#include "dev/disk_image.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
#include "sim/sim_exit.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Raw Disk image
|
||||
//
|
||||
RawDiskImage::RawDiskImage(const Params* p)
|
||||
: DiskImage(p), disk_size(0)
|
||||
{ open(p->image_file, p->read_only); }
|
||||
|
||||
RawDiskImage::~RawDiskImage()
|
||||
{ close(); }
|
||||
|
||||
void
|
||||
RawDiskImage::open(const string &filename, bool rd_only)
|
||||
{
|
||||
if (!filename.empty()) {
|
||||
initialized = true;
|
||||
readonly = rd_only;
|
||||
file = filename;
|
||||
|
||||
ios::openmode mode = ios::in | ios::binary;
|
||||
if (!readonly)
|
||||
mode |= ios::out;
|
||||
stream.open(file.c_str(), mode);
|
||||
if (!stream.is_open())
|
||||
panic("Error opening %s", filename);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RawDiskImage::close()
|
||||
{
|
||||
stream.close();
|
||||
}
|
||||
|
||||
off_t
|
||||
RawDiskImage::size() const
|
||||
{
|
||||
if (disk_size == 0) {
|
||||
if (!stream.is_open())
|
||||
panic("file not open!\n");
|
||||
stream.seekg(0, ios::end);
|
||||
disk_size = stream.tellg();
|
||||
}
|
||||
|
||||
return disk_size / SectorSize;
|
||||
}
|
||||
|
||||
off_t
|
||||
RawDiskImage::read(uint8_t *data, off_t offset) const
|
||||
{
|
||||
if (!initialized)
|
||||
panic("RawDiskImage not initialized");
|
||||
|
||||
if (!stream.is_open())
|
||||
panic("file not open!\n");
|
||||
|
||||
if (stream.seekg(offset * SectorSize, ios::beg) < 0)
|
||||
panic("Could not seek to location in file");
|
||||
|
||||
streampos pos = stream.tellg();
|
||||
stream.read((char *)data, SectorSize);
|
||||
|
||||
DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
|
||||
DDUMP(DiskImageRead, data, SectorSize);
|
||||
|
||||
return stream.tellg() - pos;
|
||||
}
|
||||
|
||||
off_t
|
||||
RawDiskImage::write(const uint8_t *data, off_t offset)
|
||||
{
|
||||
if (!initialized)
|
||||
panic("RawDiskImage not initialized");
|
||||
|
||||
if (readonly)
|
||||
panic("Cannot write to a read only disk image");
|
||||
|
||||
if (!stream.is_open())
|
||||
panic("file not open!\n");
|
||||
|
||||
if (stream.seekp(offset * SectorSize, ios::beg) < 0)
|
||||
panic("Could not seek to location in file");
|
||||
|
||||
DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
|
||||
DDUMP(DiskImageWrite, data, SectorSize);
|
||||
|
||||
streampos pos = stream.tellp();
|
||||
stream.write((const char *)data, SectorSize);
|
||||
return stream.tellp() - pos;
|
||||
}
|
||||
|
||||
RawDiskImage *
|
||||
RawDiskImageParams::create()
|
||||
{
|
||||
return new RawDiskImage(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copy on Write Disk image
|
||||
//
|
||||
const uint32_t CowDiskImage::VersionMajor = 1;
|
||||
const uint32_t CowDiskImage::VersionMinor = 0;
|
||||
|
||||
class CowDiskCallback : public Callback
|
||||
{
|
||||
private:
|
||||
CowDiskImage *image;
|
||||
|
||||
public:
|
||||
CowDiskCallback(CowDiskImage *i) : image(i) {}
|
||||
void process() { image->save(); delete this; }
|
||||
};
|
||||
|
||||
CowDiskImage::CowDiskImage(const Params *p)
|
||||
: DiskImage(p), filename(p->image_file), child(p->child), table(NULL)
|
||||
{
|
||||
if (filename.empty()) {
|
||||
initSectorTable(p->table_size);
|
||||
} else {
|
||||
if (!open(filename)) {
|
||||
if (p->read_only)
|
||||
fatal("could not open read-only file");
|
||||
initSectorTable(p->table_size);
|
||||
}
|
||||
|
||||
if (!p->read_only)
|
||||
registerExitCallback(new CowDiskCallback(this));
|
||||
}
|
||||
}
|
||||
|
||||
CowDiskImage::~CowDiskImage()
|
||||
{
|
||||
SectorTable::iterator i = table->begin();
|
||||
SectorTable::iterator end = table->end();
|
||||
|
||||
while (i != end) {
|
||||
delete (*i).second;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SafeRead(ifstream &stream, void *data, int count)
|
||||
{
|
||||
stream.read((char *)data, count);
|
||||
if (!stream.is_open())
|
||||
panic("file not open");
|
||||
|
||||
if (stream.eof())
|
||||
panic("premature end-of-file");
|
||||
|
||||
if (stream.bad() || stream.fail())
|
||||
panic("error reading cowdisk image");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
SafeRead(ifstream &stream, T &data)
|
||||
{
|
||||
SafeRead(stream, &data, sizeof(data));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
SafeReadSwap(ifstream &stream, T &data)
|
||||
{
|
||||
SafeRead(stream, &data, sizeof(data));
|
||||
data = letoh(data); //is this the proper byte order conversion?
|
||||
}
|
||||
|
||||
bool
|
||||
CowDiskImage::open(const string &file)
|
||||
{
|
||||
ifstream stream(file.c_str());
|
||||
if (!stream.is_open())
|
||||
return false;
|
||||
|
||||
if (stream.fail() || stream.bad())
|
||||
panic("Error opening %s", file);
|
||||
|
||||
uint64_t magic;
|
||||
SafeRead(stream, magic);
|
||||
|
||||
if (memcmp(&magic, "COWDISK!", sizeof(magic)) != 0)
|
||||
panic("Could not open %s: Invalid magic", file);
|
||||
|
||||
uint32_t major, minor;
|
||||
SafeReadSwap(stream, major);
|
||||
SafeReadSwap(stream, minor);
|
||||
|
||||
if (major != VersionMajor && minor != VersionMinor)
|
||||
panic("Could not open %s: invalid version %d.%d != %d.%d",
|
||||
file, major, minor, VersionMajor, VersionMinor);
|
||||
|
||||
uint64_t sector_count;
|
||||
SafeReadSwap(stream, sector_count);
|
||||
table = new SectorTable(sector_count);
|
||||
|
||||
|
||||
for (uint64_t i = 0; i < sector_count; i++) {
|
||||
uint64_t offset;
|
||||
SafeReadSwap(stream, offset);
|
||||
|
||||
Sector *sector = new Sector;
|
||||
SafeRead(stream, sector, sizeof(Sector));
|
||||
|
||||
assert(table->find(offset) == table->end());
|
||||
(*table)[offset] = sector;
|
||||
}
|
||||
|
||||
stream.close();
|
||||
|
||||
initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CowDiskImage::initSectorTable(int hash_size)
|
||||
{
|
||||
table = new SectorTable(hash_size);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void
|
||||
SafeWrite(ofstream &stream, const void *data, int count)
|
||||
{
|
||||
stream.write((const char *)data, count);
|
||||
if (!stream.is_open())
|
||||
panic("file not open");
|
||||
|
||||
if (stream.eof())
|
||||
panic("premature end-of-file");
|
||||
|
||||
if (stream.bad() || stream.fail())
|
||||
panic("error reading cowdisk image");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
SafeWrite(ofstream &stream, const T &data)
|
||||
{
|
||||
SafeWrite(stream, &data, sizeof(data));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
SafeWriteSwap(ofstream &stream, const T &data)
|
||||
{
|
||||
T swappeddata = letoh(data); //is this the proper byte order conversion?
|
||||
SafeWrite(stream, &swappeddata, sizeof(data));
|
||||
}
|
||||
void
|
||||
CowDiskImage::save()
|
||||
{
|
||||
save(filename);
|
||||
}
|
||||
|
||||
void
|
||||
CowDiskImage::save(const string &file)
|
||||
{
|
||||
if (!initialized)
|
||||
panic("RawDiskImage not initialized");
|
||||
|
||||
ofstream stream(file.c_str());
|
||||
if (!stream.is_open() || stream.fail() || stream.bad())
|
||||
panic("Error opening %s", file);
|
||||
|
||||
uint64_t magic;
|
||||
memcpy(&magic, "COWDISK!", sizeof(magic));
|
||||
SafeWrite(stream, magic);
|
||||
|
||||
SafeWriteSwap(stream, (uint32_t)VersionMajor);
|
||||
SafeWriteSwap(stream, (uint32_t)VersionMinor);
|
||||
SafeWriteSwap(stream, (uint64_t)table->size());
|
||||
|
||||
uint64_t size = table->size();
|
||||
SectorTable::iterator iter = table->begin();
|
||||
SectorTable::iterator end = table->end();
|
||||
|
||||
for (uint64_t i = 0; i < size; i++) {
|
||||
if (iter == end)
|
||||
panic("Incorrect Table Size during save of COW disk image");
|
||||
|
||||
SafeWriteSwap(stream, (uint64_t)(*iter).first);
|
||||
SafeWrite(stream, (*iter).second->data, sizeof(Sector));
|
||||
++iter;
|
||||
}
|
||||
|
||||
stream.close();
|
||||
}
|
||||
|
||||
void
|
||||
CowDiskImage::writeback()
|
||||
{
|
||||
SectorTable::iterator i = table->begin();
|
||||
SectorTable::iterator end = table->end();
|
||||
|
||||
while (i != end) {
|
||||
child->write((*i).second->data, (*i).first);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
off_t
|
||||
CowDiskImage::size() const
|
||||
{ return child->size(); }
|
||||
|
||||
off_t
|
||||
CowDiskImage::read(uint8_t *data, off_t offset) const
|
||||
{
|
||||
if (!initialized)
|
||||
panic("CowDiskImage not initialized");
|
||||
|
||||
if (offset > size())
|
||||
panic("access out of bounds");
|
||||
|
||||
SectorTable::const_iterator i = table->find(offset);
|
||||
if (i == table->end())
|
||||
return child->read(data, offset);
|
||||
else {
|
||||
memcpy(data, (*i).second->data, SectorSize);
|
||||
DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
|
||||
DDUMP(DiskImageRead, data, SectorSize);
|
||||
return SectorSize;
|
||||
}
|
||||
}
|
||||
|
||||
off_t
|
||||
CowDiskImage::write(const uint8_t *data, off_t offset)
|
||||
{
|
||||
if (!initialized)
|
||||
panic("RawDiskImage not initialized");
|
||||
|
||||
if (offset > size())
|
||||
panic("access out of bounds");
|
||||
|
||||
SectorTable::iterator i = table->find(offset);
|
||||
if (i == table->end()) {
|
||||
Sector *sector = new Sector;
|
||||
memcpy(sector, data, SectorSize);
|
||||
table->insert(make_pair(offset, sector));
|
||||
} else {
|
||||
memcpy((*i).second->data, data, SectorSize);
|
||||
}
|
||||
|
||||
DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
|
||||
DDUMP(DiskImageWrite, data, SectorSize);
|
||||
|
||||
return SectorSize;
|
||||
}
|
||||
|
||||
void
|
||||
CowDiskImage::serialize(ostream &os)
|
||||
{
|
||||
string cowFilename = name() + ".cow";
|
||||
SERIALIZE_SCALAR(cowFilename);
|
||||
save(Checkpoint::dir() + "/" + cowFilename);
|
||||
}
|
||||
|
||||
void
|
||||
CowDiskImage::unserialize(Checkpoint *cp, const string §ion)
|
||||
{
|
||||
string cowFilename;
|
||||
UNSERIALIZE_SCALAR(cowFilename);
|
||||
cowFilename = cp->cptDir + "/" + cowFilename;
|
||||
open(cowFilename);
|
||||
}
|
||||
|
||||
CowDiskImage *
|
||||
CowDiskImageParams::create()
|
||||
{
|
||||
return new CowDiskImage(this);
|
||||
}
|
||||
138
simulators/gem5/src/dev/disk_image.hh
Normal file
138
simulators/gem5/src/dev/disk_image.hh
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Disk Image Interfaces
|
||||
*/
|
||||
|
||||
#ifndef __DISK_IMAGE_HH__
|
||||
#define __DISK_IMAGE_HH__
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "base/hashmap.hh"
|
||||
#include "params/CowDiskImage.hh"
|
||||
#include "params/DiskImage.hh"
|
||||
#include "params/RawDiskImage.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
#define SectorSize (512)
|
||||
|
||||
/**
|
||||
* Basic interface for accessing a disk image.
|
||||
*/
|
||||
class DiskImage : public SimObject
|
||||
{
|
||||
protected:
|
||||
bool initialized;
|
||||
|
||||
public:
|
||||
typedef DiskImageParams Params;
|
||||
DiskImage(const Params *p) : SimObject(p), initialized(false) {}
|
||||
virtual ~DiskImage() {}
|
||||
|
||||
virtual off_t size() const = 0;
|
||||
|
||||
virtual off_t read(uint8_t *data, off_t offset) const = 0;
|
||||
virtual off_t write(const uint8_t *data, off_t offset) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Specialization for accessing a raw disk image
|
||||
*/
|
||||
class RawDiskImage : public DiskImage
|
||||
{
|
||||
protected:
|
||||
mutable std::fstream stream;
|
||||
std::string file;
|
||||
bool readonly;
|
||||
mutable off_t disk_size;
|
||||
|
||||
public:
|
||||
typedef RawDiskImageParams Params;
|
||||
RawDiskImage(const Params *p);
|
||||
~RawDiskImage();
|
||||
|
||||
void close();
|
||||
void open(const std::string &filename, bool rd_only = false);
|
||||
|
||||
virtual off_t size() const;
|
||||
|
||||
virtual off_t read(uint8_t *data, off_t offset) const;
|
||||
virtual off_t write(const uint8_t *data, off_t offset);
|
||||
};
|
||||
|
||||
/**
|
||||
* Specialization for accessing a copy-on-write disk image layer.
|
||||
* A copy-on-write(COW) layer must be stacked on top of another disk
|
||||
* image layer this layer can be another CowDiskImage, or a
|
||||
* RawDiskImage.
|
||||
*
|
||||
* This object is designed to provide a mechanism for persistant
|
||||
* changes to a main disk image, or to provide a place for temporary
|
||||
* changes to the image to take place that later may be thrown away.
|
||||
*/
|
||||
class CowDiskImage : public DiskImage
|
||||
{
|
||||
public:
|
||||
static const uint32_t VersionMajor;
|
||||
static const uint32_t VersionMinor;
|
||||
|
||||
protected:
|
||||
struct Sector {
|
||||
uint8_t data[SectorSize];
|
||||
};
|
||||
typedef m5::hash_map<uint64_t, Sector *> SectorTable;
|
||||
|
||||
protected:
|
||||
std::string filename;
|
||||
DiskImage *child;
|
||||
SectorTable *table;
|
||||
|
||||
public:
|
||||
typedef CowDiskImageParams Params;
|
||||
CowDiskImage(const Params *p);
|
||||
~CowDiskImage();
|
||||
|
||||
void initSectorTable(int hash_size);
|
||||
bool open(const std::string &file);
|
||||
void save();
|
||||
void save(const std::string &file);
|
||||
void writeback();
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
virtual off_t size() const;
|
||||
|
||||
virtual off_t read(uint8_t *data, off_t offset) const;
|
||||
virtual off_t write(const uint8_t *data, off_t offset);
|
||||
};
|
||||
|
||||
#endif // __DISK_IMAGE_HH__
|
||||
310
simulators/gem5/src/dev/dma_device.cc
Normal file
310
simulators/gem5/src/dev/dma_device.cc
Normal file
@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
* Nathan Binkert
|
||||
*/
|
||||
|
||||
#include "base/chunk_generator.hh"
|
||||
#include "debug/DMA.hh"
|
||||
#include "dev/dma_device.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
DmaPort::DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff)
|
||||
: MasterPort(dev->name() + "-dma", dev), device(dev), sys(s),
|
||||
masterId(s->getMasterId(dev->name())),
|
||||
pendingCount(0), actionInProgress(0), drainEvent(NULL),
|
||||
backoffTime(0), minBackoffDelay(min_backoff),
|
||||
maxBackoffDelay(max_backoff), inRetry(false),
|
||||
backoffEvent(this)
|
||||
{ }
|
||||
|
||||
bool
|
||||
DmaPort::recvTimingResp(PacketPtr pkt)
|
||||
{
|
||||
if (pkt->wasNacked()) {
|
||||
DPRINTF(DMA, "Received nacked %s addr %#x\n",
|
||||
pkt->cmdString(), pkt->getAddr());
|
||||
|
||||
if (backoffTime < minBackoffDelay)
|
||||
backoffTime = minBackoffDelay;
|
||||
else if (backoffTime < maxBackoffDelay)
|
||||
backoffTime <<= 1;
|
||||
|
||||
device->reschedule(backoffEvent, curTick() + backoffTime, true);
|
||||
|
||||
DPRINTF(DMA, "Backoff time set to %d ticks\n", backoffTime);
|
||||
|
||||
pkt->reinitNacked();
|
||||
queueDma(pkt, true);
|
||||
} else if (pkt->senderState) {
|
||||
DmaReqState *state;
|
||||
backoffTime >>= 2;
|
||||
|
||||
DPRINTF(DMA, "Received response %s addr %#x size %#x\n",
|
||||
pkt->cmdString(), pkt->getAddr(), pkt->req->getSize());
|
||||
state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
||||
pendingCount--;
|
||||
|
||||
assert(pendingCount >= 0);
|
||||
assert(state);
|
||||
|
||||
// We shouldn't ever get a block in ownership state
|
||||
assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted()));
|
||||
|
||||
state->numBytes += pkt->req->getSize();
|
||||
assert(state->totBytes >= state->numBytes);
|
||||
if (state->totBytes == state->numBytes) {
|
||||
if (state->completionEvent) {
|
||||
if (state->delay)
|
||||
device->schedule(state->completionEvent,
|
||||
curTick() + state->delay);
|
||||
else
|
||||
state->completionEvent->process();
|
||||
}
|
||||
delete state;
|
||||
}
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
|
||||
if (pendingCount == 0 && drainEvent) {
|
||||
drainEvent->process();
|
||||
drainEvent = NULL;
|
||||
}
|
||||
} else {
|
||||
panic("Got packet without sender state... huh?\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DmaDevice::DmaDevice(const Params *p)
|
||||
: PioDevice(p), dmaPort(this, sys, params()->min_backoff_delay,
|
||||
params()->max_backoff_delay)
|
||||
{ }
|
||||
|
||||
void
|
||||
DmaDevice::init()
|
||||
{
|
||||
if (!dmaPort.isConnected())
|
||||
panic("DMA port of %s not connected to anything!", name());
|
||||
PioDevice::init();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
DmaDevice::drain(Event *de)
|
||||
{
|
||||
unsigned int count;
|
||||
count = pioPort.drain(de) + dmaPort.drain(de);
|
||||
if (count)
|
||||
changeState(Draining);
|
||||
else
|
||||
changeState(Drained);
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
DmaPort::drain(Event *de)
|
||||
{
|
||||
if (pendingCount == 0)
|
||||
return 0;
|
||||
drainEvent = de;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
DmaPort::recvRetry()
|
||||
{
|
||||
assert(transmitList.size());
|
||||
bool result = true;
|
||||
do {
|
||||
PacketPtr pkt = transmitList.front();
|
||||
DPRINTF(DMA, "Retry on %s addr %#x\n",
|
||||
pkt->cmdString(), pkt->getAddr());
|
||||
result = sendTimingReq(pkt);
|
||||
if (result) {
|
||||
DPRINTF(DMA, "-- Done\n");
|
||||
transmitList.pop_front();
|
||||
inRetry = false;
|
||||
} else {
|
||||
inRetry = true;
|
||||
DPRINTF(DMA, "-- Failed, queued\n");
|
||||
}
|
||||
} while (!backoffTime && result && transmitList.size());
|
||||
|
||||
if (transmitList.size() && backoffTime && !inRetry) {
|
||||
DPRINTF(DMA, "Scheduling backoff for %d\n", curTick()+backoffTime);
|
||||
if (!backoffEvent.scheduled())
|
||||
device->schedule(backoffEvent, backoffTime + curTick());
|
||||
}
|
||||
DPRINTF(DMA, "TransmitList: %d, backoffTime: %d inRetry: %d es: %d\n",
|
||||
transmitList.size(), backoffTime, inRetry,
|
||||
backoffEvent.scheduled());
|
||||
}
|
||||
|
||||
void
|
||||
DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
|
||||
uint8_t *data, Tick delay, Request::Flags flag)
|
||||
{
|
||||
assert(device->getState() == SimObject::Running);
|
||||
|
||||
DmaReqState *reqState = new DmaReqState(event, size, delay);
|
||||
|
||||
|
||||
DPRINTF(DMA, "Starting DMA for addr: %#x size: %d sched: %d\n", addr, size,
|
||||
event ? event->scheduled() : -1 );
|
||||
for (ChunkGenerator gen(addr, size, peerBlockSize());
|
||||
!gen.done(); gen.next()) {
|
||||
Request *req = new Request(gen.addr(), gen.size(), flag, masterId);
|
||||
PacketPtr pkt = new Packet(req, cmd);
|
||||
|
||||
// Increment the data pointer on a write
|
||||
if (data)
|
||||
pkt->dataStatic(data + gen.complete());
|
||||
|
||||
pkt->senderState = reqState;
|
||||
|
||||
assert(pendingCount >= 0);
|
||||
pendingCount++;
|
||||
DPRINTF(DMA, "--Queuing DMA for addr: %#x size: %d\n", gen.addr(),
|
||||
gen.size());
|
||||
queueDma(pkt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
DmaPort::queueDma(PacketPtr pkt, bool front)
|
||||
{
|
||||
|
||||
if (front)
|
||||
transmitList.push_front(pkt);
|
||||
else
|
||||
transmitList.push_back(pkt);
|
||||
sendDma();
|
||||
}
|
||||
|
||||
void
|
||||
DmaPort::sendDma()
|
||||
{
|
||||
// some kind of selction between access methods
|
||||
// more work is going to have to be done to make
|
||||
// switching actually work
|
||||
assert(transmitList.size());
|
||||
PacketPtr pkt = transmitList.front();
|
||||
|
||||
Enums::MemoryMode state = sys->getMemoryMode();
|
||||
if (state == Enums::timing) {
|
||||
if (backoffEvent.scheduled() || inRetry) {
|
||||
DPRINTF(DMA, "Can't send immediately, waiting for retry or backoff timer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINTF(DMA, "Attempting to send %s addr %#x\n",
|
||||
pkt->cmdString(), pkt->getAddr());
|
||||
|
||||
bool result;
|
||||
do {
|
||||
result = sendTimingReq(pkt);
|
||||
if (result) {
|
||||
transmitList.pop_front();
|
||||
DPRINTF(DMA, "-- Done\n");
|
||||
} else {
|
||||
inRetry = true;
|
||||
DPRINTF(DMA, "-- Failed: queued\n");
|
||||
}
|
||||
} while (result && !backoffTime && transmitList.size());
|
||||
|
||||
if (transmitList.size() && backoffTime && !inRetry &&
|
||||
!backoffEvent.scheduled()) {
|
||||
DPRINTF(DMA, "-- Scheduling backoff timer for %d\n",
|
||||
backoffTime+curTick());
|
||||
device->schedule(backoffEvent, backoffTime + curTick());
|
||||
}
|
||||
} else if (state == Enums::atomic) {
|
||||
transmitList.pop_front();
|
||||
|
||||
Tick lat;
|
||||
DPRINTF(DMA, "--Sending DMA for addr: %#x size: %d\n",
|
||||
pkt->req->getPaddr(), pkt->req->getSize());
|
||||
lat = sendAtomic(pkt);
|
||||
assert(pkt->senderState);
|
||||
DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
||||
assert(state);
|
||||
state->numBytes += pkt->req->getSize();
|
||||
|
||||
DPRINTF(DMA, "--Received response for DMA for addr: %#x size: %d nb: %d, tot: %d sched %d\n",
|
||||
pkt->req->getPaddr(), pkt->req->getSize(), state->numBytes,
|
||||
state->totBytes,
|
||||
state->completionEvent ? state->completionEvent->scheduled() : 0 );
|
||||
|
||||
if (state->totBytes == state->numBytes) {
|
||||
if (state->completionEvent) {
|
||||
assert(!state->completionEvent->scheduled());
|
||||
device->schedule(state->completionEvent,
|
||||
curTick() + lat + state->delay);
|
||||
}
|
||||
delete state;
|
||||
delete pkt->req;
|
||||
}
|
||||
pendingCount--;
|
||||
assert(pendingCount >= 0);
|
||||
delete pkt;
|
||||
|
||||
if (pendingCount == 0 && drainEvent) {
|
||||
drainEvent->process();
|
||||
drainEvent = NULL;
|
||||
}
|
||||
|
||||
} else
|
||||
panic("Unknown memory command state.");
|
||||
}
|
||||
|
||||
DmaDevice::~DmaDevice()
|
||||
{
|
||||
}
|
||||
|
||||
MasterPort &
|
||||
DmaDevice::getMasterPort(const std::string &if_name, int idx)
|
||||
{
|
||||
if (if_name == "dma") {
|
||||
return dmaPort;
|
||||
}
|
||||
return PioDevice::getMasterPort(if_name, idx);
|
||||
}
|
||||
171
simulators/gem5/src/dev/dma_device.hh
Normal file
171
simulators/gem5/src/dev/dma_device.hh
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Nathan Binkert
|
||||
*/
|
||||
|
||||
#ifndef __DEV_DMA_DEVICE_HH__
|
||||
#define __DEV_DMA_DEVICE_HH__
|
||||
|
||||
#include "dev/io_device.hh"
|
||||
#include "params/DmaDevice.hh"
|
||||
|
||||
class DmaPort : public MasterPort
|
||||
{
|
||||
protected:
|
||||
struct DmaReqState : public Packet::SenderState
|
||||
{
|
||||
/** Event to call on the device when this transaction (all packets)
|
||||
* complete. */
|
||||
Event *completionEvent;
|
||||
|
||||
/** Total number of bytes that this transaction involves. */
|
||||
Addr totBytes;
|
||||
|
||||
/** Number of bytes that have been acked for this transaction. */
|
||||
Addr numBytes;
|
||||
|
||||
/** Amount to delay completion of dma by */
|
||||
Tick delay;
|
||||
|
||||
DmaReqState(Event *ce, Addr tb, Tick _delay)
|
||||
: completionEvent(ce), totBytes(tb), numBytes(0), delay(_delay)
|
||||
{}
|
||||
};
|
||||
|
||||
MemObject *device;
|
||||
std::list<PacketPtr> transmitList;
|
||||
|
||||
/** The system that device/port are in. This is used to select which mode
|
||||
* we are currently operating in. */
|
||||
System *sys;
|
||||
|
||||
/** Id for all requests */
|
||||
MasterID masterId;
|
||||
|
||||
/** Number of outstanding packets the dma port has. */
|
||||
int pendingCount;
|
||||
|
||||
/** If a dmaAction is in progress. */
|
||||
int actionInProgress;
|
||||
|
||||
/** If we need to drain, keep the drain event around until we're done
|
||||
* here.*/
|
||||
Event *drainEvent;
|
||||
|
||||
/** time to wait between sending another packet, increases as NACKs are
|
||||
* recived, decreases as responses are recived. */
|
||||
Tick backoffTime;
|
||||
|
||||
/** Minimum time that device should back off for after failed sendTiming */
|
||||
Tick minBackoffDelay;
|
||||
|
||||
/** Maximum time that device should back off for after failed sendTiming */
|
||||
Tick maxBackoffDelay;
|
||||
|
||||
/** If the port is currently waiting for a retry before it can send whatever
|
||||
* it is that it's sending. */
|
||||
bool inRetry;
|
||||
|
||||
virtual bool recvTimingResp(PacketPtr pkt);
|
||||
|
||||
virtual void recvRetry() ;
|
||||
|
||||
void queueDma(PacketPtr pkt, bool front = false);
|
||||
void sendDma();
|
||||
|
||||
/** event to give us a kick every time we backoff time is reached. */
|
||||
EventWrapper<DmaPort, &DmaPort::sendDma> backoffEvent;
|
||||
|
||||
public:
|
||||
DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff);
|
||||
|
||||
void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
|
||||
uint8_t *data, Tick delay, Request::Flags flag = 0);
|
||||
|
||||
bool dmaPending() { return pendingCount > 0; }
|
||||
|
||||
unsigned cacheBlockSize() const { return peerBlockSize(); }
|
||||
unsigned int drain(Event *de);
|
||||
};
|
||||
|
||||
class DmaDevice : public PioDevice
|
||||
{
|
||||
protected:
|
||||
DmaPort dmaPort;
|
||||
|
||||
public:
|
||||
typedef DmaDeviceParams Params;
|
||||
DmaDevice(const Params *p);
|
||||
virtual ~DmaDevice();
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data,
|
||||
Tick delay = 0)
|
||||
{
|
||||
dmaPort.dmaAction(MemCmd::WriteReq, addr, size, event, data, delay);
|
||||
}
|
||||
|
||||
void dmaRead(Addr addr, int size, Event *event, uint8_t *data,
|
||||
Tick delay = 0)
|
||||
{
|
||||
dmaPort.dmaAction(MemCmd::ReadReq, addr, size, event, data, delay);
|
||||
}
|
||||
|
||||
bool dmaPending() { return dmaPort.dmaPending(); }
|
||||
|
||||
virtual void init();
|
||||
|
||||
virtual unsigned int drain(Event *de);
|
||||
|
||||
unsigned cacheBlockSize() const { return dmaPort.cacheBlockSize(); }
|
||||
|
||||
virtual MasterPort &getMasterPort(const std::string &if_name,
|
||||
int idx = -1);
|
||||
|
||||
friend class DmaPort;
|
||||
};
|
||||
|
||||
#endif // __DEV_DMA_DEVICE_HH__
|
||||
113
simulators/gem5/src/dev/etherbus.cc
Normal file
113
simulators/gem5/src/dev/etherbus.cc
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* Device module for modelling an ethernet hub
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "debug/Ethernet.hh"
|
||||
#include "debug/EthernetData.hh"
|
||||
#include "dev/etherbus.hh"
|
||||
#include "dev/etherdump.hh"
|
||||
#include "dev/etherint.hh"
|
||||
#include "dev/etherpkt.hh"
|
||||
#include "params/EtherBus.hh"
|
||||
#include "sim/core.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
EtherBus::EtherBus(const Params *p)
|
||||
: EtherObject(p), ticksPerByte(p->speed), loopback(p->loopback),
|
||||
event(this), sender(0), dump(p->dump)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
EtherBus::txDone()
|
||||
{
|
||||
devlist_t::iterator i = devlist.begin();
|
||||
devlist_t::iterator end = devlist.end();
|
||||
|
||||
DPRINTF(Ethernet, "ethernet packet received: length=%d\n", packet->length);
|
||||
DDUMP(EthernetData, packet->data, packet->length);
|
||||
|
||||
while (i != end) {
|
||||
if (loopback || *i != sender)
|
||||
(*i)->sendPacket(packet);
|
||||
++i;
|
||||
}
|
||||
|
||||
sender->sendDone();
|
||||
|
||||
if (dump)
|
||||
dump->dump(packet);
|
||||
|
||||
sender = 0;
|
||||
packet = 0;
|
||||
}
|
||||
|
||||
EtherInt*
|
||||
EtherBus::getEthPort(const std::string &if_name, int idx)
|
||||
{
|
||||
panic("Etherbus doesn't work\n");
|
||||
}
|
||||
|
||||
bool
|
||||
EtherBus::send(EtherInt *sndr, EthPacketPtr &pkt)
|
||||
{
|
||||
if (busy()) {
|
||||
DPRINTF(Ethernet, "ethernet packet not sent, bus busy\n", curTick());
|
||||
return false;
|
||||
}
|
||||
|
||||
DPRINTF(Ethernet, "ethernet packet sent: length=%d\n", pkt->length);
|
||||
DDUMP(EthernetData, pkt->data, pkt->length);
|
||||
|
||||
packet = pkt;
|
||||
sender = sndr;
|
||||
int delay = (int)ceil(((double)pkt->length * ticksPerByte) + 1.0);
|
||||
DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
|
||||
delay, ticksPerByte);
|
||||
schedule(event, curTick() + delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EtherBus *
|
||||
EtherBusParams::create()
|
||||
{
|
||||
return new EtherBus(this);
|
||||
}
|
||||
90
simulators/gem5/src/dev/etherbus.hh
Normal file
90
simulators/gem5/src/dev/etherbus.hh
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* Device module for modelling an ethernet hub
|
||||
*/
|
||||
|
||||
#ifndef __ETHERBUS_H__
|
||||
#define __ETHERBUS_H__
|
||||
|
||||
#include "dev/etherobject.hh"
|
||||
#include "dev/etherpkt.hh"
|
||||
#include "params/EtherBus.hh"
|
||||
#include "sim/eventq.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
class EtherDump;
|
||||
class EtherInt;
|
||||
class EtherBus : public EtherObject
|
||||
{
|
||||
protected:
|
||||
typedef std::list<EtherInt *> devlist_t;
|
||||
devlist_t devlist;
|
||||
double ticksPerByte;
|
||||
bool loopback;
|
||||
|
||||
protected:
|
||||
class DoneEvent : public Event
|
||||
{
|
||||
protected:
|
||||
EtherBus *bus;
|
||||
|
||||
public:
|
||||
DoneEvent(EtherBus *b) : bus(b) {}
|
||||
virtual void process() { bus->txDone(); }
|
||||
virtual const char *description() const
|
||||
{ return "ethernet bus completion"; }
|
||||
};
|
||||
|
||||
DoneEvent event;
|
||||
EthPacketPtr packet;
|
||||
EtherInt *sender;
|
||||
EtherDump *dump;
|
||||
|
||||
public:
|
||||
typedef EtherBusParams Params;
|
||||
EtherBus(const Params *p);
|
||||
virtual ~EtherBus() {}
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
void txDone();
|
||||
void reg(EtherInt *dev);
|
||||
bool busy() const { return (bool)packet; }
|
||||
bool send(EtherInt *sender, EthPacketPtr &packet);
|
||||
virtual EtherInt *getEthPort(const std::string &if_name, int idx);
|
||||
};
|
||||
|
||||
#endif // __ETHERBUS_H__
|
||||
368
simulators/gem5/src/dev/etherdevice.cc
Normal file
368
simulators/gem5/src/dev/etherdevice.cc
Normal file
@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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: Nathan Binkert
|
||||
* Lisa Hsu
|
||||
*/
|
||||
|
||||
#include "dev/etherdevice.hh"
|
||||
#include "sim/stats.hh"
|
||||
|
||||
void
|
||||
EtherDevice::regStats()
|
||||
{
|
||||
txBytes
|
||||
.name(name() + ".txBytes")
|
||||
.desc("Bytes Transmitted")
|
||||
.prereq(txBytes)
|
||||
;
|
||||
|
||||
rxBytes
|
||||
.name(name() + ".rxBytes")
|
||||
.desc("Bytes Received")
|
||||
.prereq(rxBytes)
|
||||
;
|
||||
|
||||
txPackets
|
||||
.name(name() + ".txPackets")
|
||||
.desc("Number of Packets Transmitted")
|
||||
.prereq(txBytes)
|
||||
;
|
||||
|
||||
rxPackets
|
||||
.name(name() + ".rxPackets")
|
||||
.desc("Number of Packets Received")
|
||||
.prereq(rxBytes)
|
||||
;
|
||||
|
||||
txIpChecksums
|
||||
.name(name() + ".txIpChecksums")
|
||||
.desc("Number of tx IP Checksums done by device")
|
||||
.precision(0)
|
||||
.prereq(txBytes)
|
||||
;
|
||||
|
||||
rxIpChecksums
|
||||
.name(name() + ".rxIpChecksums")
|
||||
.desc("Number of rx IP Checksums done by device")
|
||||
.precision(0)
|
||||
.prereq(rxBytes)
|
||||
;
|
||||
|
||||
txTcpChecksums
|
||||
.name(name() + ".txTcpChecksums")
|
||||
.desc("Number of tx TCP Checksums done by device")
|
||||
.precision(0)
|
||||
.prereq(txBytes)
|
||||
;
|
||||
|
||||
rxTcpChecksums
|
||||
.name(name() + ".rxTcpChecksums")
|
||||
.desc("Number of rx TCP Checksums done by device")
|
||||
.precision(0)
|
||||
.prereq(rxBytes)
|
||||
;
|
||||
|
||||
txUdpChecksums
|
||||
.name(name() + ".txUdpChecksums")
|
||||
.desc("Number of tx UDP Checksums done by device")
|
||||
.precision(0)
|
||||
.prereq(txBytes)
|
||||
;
|
||||
|
||||
rxUdpChecksums
|
||||
.name(name() + ".rxUdpChecksums")
|
||||
.desc("Number of rx UDP Checksums done by device")
|
||||
.precision(0)
|
||||
.prereq(rxBytes)
|
||||
;
|
||||
|
||||
descDmaReads
|
||||
.name(name() + ".descDMAReads")
|
||||
.desc("Number of descriptors the device read w/ DMA")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
descDmaWrites
|
||||
.name(name() + ".descDMAWrites")
|
||||
.desc("Number of descriptors the device wrote w/ DMA")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
descDmaRdBytes
|
||||
.name(name() + ".descDmaReadBytes")
|
||||
.desc("number of descriptor bytes read w/ DMA")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
descDmaWrBytes
|
||||
.name(name() + ".descDmaWriteBytes")
|
||||
.desc("number of descriptor bytes write w/ DMA")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
txBandwidth
|
||||
.name(name() + ".txBandwidth")
|
||||
.desc("Transmit Bandwidth (bits/s)")
|
||||
.precision(0)
|
||||
.prereq(txBytes)
|
||||
;
|
||||
|
||||
rxBandwidth
|
||||
.name(name() + ".rxBandwidth")
|
||||
.desc("Receive Bandwidth (bits/s)")
|
||||
.precision(0)
|
||||
.prereq(rxBytes)
|
||||
;
|
||||
|
||||
totBandwidth
|
||||
.name(name() + ".totBandwidth")
|
||||
.desc("Total Bandwidth (bits/s)")
|
||||
.precision(0)
|
||||
.prereq(totBytes)
|
||||
;
|
||||
|
||||
totPackets
|
||||
.name(name() + ".totPackets")
|
||||
.desc("Total Packets")
|
||||
.precision(0)
|
||||
.prereq(totBytes)
|
||||
;
|
||||
|
||||
totBytes
|
||||
.name(name() + ".totBytes")
|
||||
.desc("Total Bytes")
|
||||
.precision(0)
|
||||
.prereq(totBytes)
|
||||
;
|
||||
|
||||
totPacketRate
|
||||
.name(name() + ".totPPS")
|
||||
.desc("Total Tranmission Rate (packets/s)")
|
||||
.precision(0)
|
||||
.prereq(totBytes)
|
||||
;
|
||||
|
||||
txPacketRate
|
||||
.name(name() + ".txPPS")
|
||||
.desc("Packet Tranmission Rate (packets/s)")
|
||||
.precision(0)
|
||||
.prereq(txBytes)
|
||||
;
|
||||
|
||||
rxPacketRate
|
||||
.name(name() + ".rxPPS")
|
||||
.desc("Packet Reception Rate (packets/s)")
|
||||
.precision(0)
|
||||
.prereq(rxBytes)
|
||||
;
|
||||
|
||||
postedSwi
|
||||
.name(name() + ".postedSwi")
|
||||
.desc("number of software interrupts posted to CPU")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
totalSwi
|
||||
.name(name() + ".totalSwi")
|
||||
.desc("total number of Swi written to ISR")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
coalescedSwi
|
||||
.name(name() + ".coalescedSwi")
|
||||
.desc("average number of Swi's coalesced into each post")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
postedRxIdle
|
||||
.name(name() + ".postedRxIdle")
|
||||
.desc("number of rxIdle interrupts posted to CPU")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
totalRxIdle
|
||||
.name(name() + ".totalRxIdle")
|
||||
.desc("total number of RxIdle written to ISR")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
coalescedRxIdle
|
||||
.name(name() + ".coalescedRxIdle")
|
||||
.desc("average number of RxIdle's coalesced into each post")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
postedRxOk
|
||||
.name(name() + ".postedRxOk")
|
||||
.desc("number of RxOk interrupts posted to CPU")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
totalRxOk
|
||||
.name(name() + ".totalRxOk")
|
||||
.desc("total number of RxOk written to ISR")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
coalescedRxOk
|
||||
.name(name() + ".coalescedRxOk")
|
||||
.desc("average number of RxOk's coalesced into each post")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
postedRxDesc
|
||||
.name(name() + ".postedRxDesc")
|
||||
.desc("number of RxDesc interrupts posted to CPU")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
totalRxDesc
|
||||
.name(name() + ".totalRxDesc")
|
||||
.desc("total number of RxDesc written to ISR")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
coalescedRxDesc
|
||||
.name(name() + ".coalescedRxDesc")
|
||||
.desc("average number of RxDesc's coalesced into each post")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
postedTxOk
|
||||
.name(name() + ".postedTxOk")
|
||||
.desc("number of TxOk interrupts posted to CPU")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
totalTxOk
|
||||
.name(name() + ".totalTxOk")
|
||||
.desc("total number of TxOk written to ISR")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
coalescedTxOk
|
||||
.name(name() + ".coalescedTxOk")
|
||||
.desc("average number of TxOk's coalesced into each post")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
postedTxIdle
|
||||
.name(name() + ".postedTxIdle")
|
||||
.desc("number of TxIdle interrupts posted to CPU")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
totalTxIdle
|
||||
.name(name() + ".totalTxIdle")
|
||||
.desc("total number of TxIdle written to ISR")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
coalescedTxIdle
|
||||
.name(name() + ".coalescedTxIdle")
|
||||
.desc("average number of TxIdle's coalesced into each post")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
postedTxDesc
|
||||
.name(name() + ".postedTxDesc")
|
||||
.desc("number of TxDesc interrupts posted to CPU")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
totalTxDesc
|
||||
.name(name() + ".totalTxDesc")
|
||||
.desc("total number of TxDesc written to ISR")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
coalescedTxDesc
|
||||
.name(name() + ".coalescedTxDesc")
|
||||
.desc("average number of TxDesc's coalesced into each post")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
postedRxOrn
|
||||
.name(name() + ".postedRxOrn")
|
||||
.desc("number of RxOrn posted to CPU")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
totalRxOrn
|
||||
.name(name() + ".totalRxOrn")
|
||||
.desc("total number of RxOrn written to ISR")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
coalescedRxOrn
|
||||
.name(name() + ".coalescedRxOrn")
|
||||
.desc("average number of RxOrn's coalesced into each post")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
coalescedTotal
|
||||
.name(name() + ".coalescedTotal")
|
||||
.desc("average number of interrupts coalesced into each post")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
postedInterrupts
|
||||
.name(name() + ".postedInterrupts")
|
||||
.desc("number of posts to CPU")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
droppedPackets
|
||||
.name(name() + ".droppedPackets")
|
||||
.desc("number of packets dropped")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
coalescedSwi = totalSwi / postedInterrupts;
|
||||
coalescedRxIdle = totalRxIdle / postedInterrupts;
|
||||
coalescedRxOk = totalRxOk / postedInterrupts;
|
||||
coalescedRxDesc = totalRxDesc / postedInterrupts;
|
||||
coalescedTxOk = totalTxOk / postedInterrupts;
|
||||
coalescedTxIdle = totalTxIdle / postedInterrupts;
|
||||
coalescedTxDesc = totalTxDesc / postedInterrupts;
|
||||
coalescedRxOrn = totalRxOrn / postedInterrupts;
|
||||
|
||||
coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc +
|
||||
totalTxOk + totalTxIdle + totalTxDesc +
|
||||
totalRxOrn) / postedInterrupts;
|
||||
|
||||
txBandwidth = txBytes * Stats::constant(8) / simSeconds;
|
||||
rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
|
||||
totBandwidth = txBandwidth + rxBandwidth;
|
||||
totBytes = txBytes + rxBytes;
|
||||
totPackets = txPackets + rxPackets;
|
||||
|
||||
txPacketRate = txPackets / simSeconds;
|
||||
rxPacketRate = rxPackets / simSeconds;
|
||||
totPacketRate = totPackets / simSeconds;
|
||||
}
|
||||
123
simulators/gem5/src/dev/etherdevice.hh
Normal file
123
simulators/gem5/src/dev/etherdevice.hh
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2007 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
|
||||
* Base Ethernet Device declaration.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ETHERDEVICE_HH__
|
||||
#define __DEV_ETHERDEVICE_HH__
|
||||
|
||||
#include "base/statistics.hh"
|
||||
#include "dev/pcidev.hh"
|
||||
#include "params/EtherDevice.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
class EtherInt;
|
||||
|
||||
/**
|
||||
* The base EtherObject class, allows for an accesor function to a
|
||||
* simobj that returns the Port.
|
||||
*/
|
||||
class EtherDevice : public PciDev
|
||||
{
|
||||
public:
|
||||
typedef EtherDeviceParams Params;
|
||||
EtherDevice(const Params *params)
|
||||
: PciDev(params)
|
||||
{}
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
public:
|
||||
/** Additional function to return the Port of a memory object. */
|
||||
virtual EtherInt *getEthPort(const std::string &if_name, int idx = -1) = 0;
|
||||
|
||||
public:
|
||||
void regStats();
|
||||
|
||||
protected:
|
||||
Stats::Scalar txBytes;
|
||||
Stats::Scalar rxBytes;
|
||||
Stats::Scalar txPackets;
|
||||
Stats::Scalar rxPackets;
|
||||
Stats::Scalar txIpChecksums;
|
||||
Stats::Scalar rxIpChecksums;
|
||||
Stats::Scalar txTcpChecksums;
|
||||
Stats::Scalar rxTcpChecksums;
|
||||
Stats::Scalar txUdpChecksums;
|
||||
Stats::Scalar rxUdpChecksums;
|
||||
Stats::Scalar descDmaReads;
|
||||
Stats::Scalar descDmaWrites;
|
||||
Stats::Scalar descDmaRdBytes;
|
||||
Stats::Scalar descDmaWrBytes;
|
||||
Stats::Formula totBandwidth;
|
||||
Stats::Formula totPackets;
|
||||
Stats::Formula totBytes;
|
||||
Stats::Formula totPacketRate;
|
||||
Stats::Formula txBandwidth;
|
||||
Stats::Formula rxBandwidth;
|
||||
Stats::Formula txPacketRate;
|
||||
Stats::Formula rxPacketRate;
|
||||
Stats::Scalar postedSwi;
|
||||
Stats::Formula coalescedSwi;
|
||||
Stats::Scalar totalSwi;
|
||||
Stats::Scalar postedRxIdle;
|
||||
Stats::Formula coalescedRxIdle;
|
||||
Stats::Scalar totalRxIdle;
|
||||
Stats::Scalar postedRxOk;
|
||||
Stats::Formula coalescedRxOk;
|
||||
Stats::Scalar totalRxOk;
|
||||
Stats::Scalar postedRxDesc;
|
||||
Stats::Formula coalescedRxDesc;
|
||||
Stats::Scalar totalRxDesc;
|
||||
Stats::Scalar postedTxOk;
|
||||
Stats::Formula coalescedTxOk;
|
||||
Stats::Scalar totalTxOk;
|
||||
Stats::Scalar postedTxIdle;
|
||||
Stats::Formula coalescedTxIdle;
|
||||
Stats::Scalar totalTxIdle;
|
||||
Stats::Scalar postedTxDesc;
|
||||
Stats::Formula coalescedTxDesc;
|
||||
Stats::Scalar totalTxDesc;
|
||||
Stats::Scalar postedRxOrn;
|
||||
Stats::Formula coalescedRxOrn;
|
||||
Stats::Scalar totalRxOrn;
|
||||
Stats::Formula coalescedTotal;
|
||||
Stats::Scalar postedInterrupts;
|
||||
Stats::Scalar droppedPackets;
|
||||
};
|
||||
|
||||
#endif //__DEV_ETHERDEVICE_HH__
|
||||
110
simulators/gem5/src/dev/etherdump.cc
Normal file
110
simulators/gem5/src/dev/etherdump.cc
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* Simple object for creating a simple pcap style packet trace
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "base/misc.hh"
|
||||
#include "base/output.hh"
|
||||
#include "dev/etherdump.hh"
|
||||
#include "sim/core.hh"
|
||||
|
||||
using std::string;
|
||||
|
||||
EtherDump::EtherDump(const Params *p)
|
||||
: SimObject(p), stream(simout.create(p->file, true)),
|
||||
maxlen(p->maxlen)
|
||||
{
|
||||
}
|
||||
|
||||
#define DLT_EN10MB 1 // Ethernet (10Mb)
|
||||
#define TCPDUMP_MAGIC 0xa1b2c3d4
|
||||
#define PCAP_VERSION_MAJOR 2
|
||||
#define PCAP_VERSION_MINOR 4
|
||||
|
||||
struct pcap_file_header {
|
||||
uint32_t magic;
|
||||
uint16_t version_major;
|
||||
uint16_t version_minor;
|
||||
int32_t thiszone; // gmt to local correction
|
||||
uint32_t sigfigs; // accuracy of timestamps
|
||||
uint32_t snaplen; // max length saved portion of each pkt
|
||||
uint32_t linktype; // data link type (DLT_*)
|
||||
};
|
||||
|
||||
struct pcap_pkthdr {
|
||||
uint32_t seconds;
|
||||
uint32_t microseconds;
|
||||
uint32_t caplen; // length of portion present
|
||||
uint32_t len; // length this packet (off wire)
|
||||
};
|
||||
|
||||
void
|
||||
EtherDump::init()
|
||||
{
|
||||
struct pcap_file_header hdr;
|
||||
hdr.magic = TCPDUMP_MAGIC;
|
||||
hdr.version_major = PCAP_VERSION_MAJOR;
|
||||
hdr.version_minor = PCAP_VERSION_MINOR;
|
||||
|
||||
hdr.thiszone = 0;
|
||||
hdr.snaplen = 1500;
|
||||
hdr.sigfigs = 0;
|
||||
hdr.linktype = DLT_EN10MB;
|
||||
|
||||
stream->write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
|
||||
|
||||
stream->flush();
|
||||
}
|
||||
|
||||
void
|
||||
EtherDump::dumpPacket(EthPacketPtr &packet)
|
||||
{
|
||||
pcap_pkthdr pkthdr;
|
||||
pkthdr.seconds = curTick() / SimClock::Int::s;
|
||||
pkthdr.microseconds = (curTick() / SimClock::Int::us) % ULL(1000000);
|
||||
pkthdr.caplen = std::min(packet->length, maxlen);
|
||||
pkthdr.len = packet->length;
|
||||
stream->write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
|
||||
stream->write(reinterpret_cast<char *>(packet->data), pkthdr.caplen);
|
||||
stream->flush();
|
||||
}
|
||||
|
||||
EtherDump *
|
||||
EtherDumpParams::create()
|
||||
{
|
||||
return new EtherDump(this);
|
||||
}
|
||||
62
simulators/gem5/src/dev/etherdump.hh
Normal file
62
simulators/gem5/src/dev/etherdump.hh
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* Simple object for creating a simple pcap style packet trace
|
||||
*/
|
||||
|
||||
#ifndef __ETHERDUMP_H__
|
||||
#define __ETHERDUMP_H__
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "dev/etherpkt.hh"
|
||||
#include "params/EtherDump.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
/*
|
||||
* Simple object for creating a simple pcap style packet trace
|
||||
*/
|
||||
class EtherDump : public SimObject
|
||||
{
|
||||
private:
|
||||
std::ostream *stream;
|
||||
const unsigned maxlen;
|
||||
void dumpPacket(EthPacketPtr &packet);
|
||||
void init();
|
||||
|
||||
public:
|
||||
typedef EtherDumpParams Params;
|
||||
EtherDump(const Params *p);
|
||||
|
||||
inline void dump(EthPacketPtr &pkt) { dumpPacket(pkt); }
|
||||
};
|
||||
|
||||
#endif // __ETHERDUMP_H__
|
||||
43
simulators/gem5/src/dev/etherint.cc
Normal file
43
simulators/gem5/src/dev/etherint.cc
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
#include "base/misc.hh"
|
||||
#include "dev/etherint.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
void
|
||||
EtherInt::setPeer(EtherInt *p)
|
||||
{
|
||||
if (peer && peer != p)
|
||||
panic("You cannot change the peer once it is set.\n"
|
||||
"Current peer=%s Desired peer=%s", peer->name(), p->name());
|
||||
|
||||
peer = p;
|
||||
}
|
||||
76
simulators/gem5/src/dev/etherint.hh
Normal file
76
simulators/gem5/src/dev/etherint.hh
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* Class representing the actual interface between two ethernet
|
||||
* components.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ETHERINT_HH__
|
||||
#define __DEV_ETHERINT_HH__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "dev/etherpkt.hh"
|
||||
|
||||
/*
|
||||
* Class representing the actual interface between two ethernet
|
||||
* components. These components are intended to attach to another
|
||||
* ethernet interface on one side and whatever device on the other.
|
||||
*/
|
||||
class EtherInt
|
||||
{
|
||||
protected:
|
||||
mutable std::string portName;
|
||||
EtherInt *peer;
|
||||
|
||||
public:
|
||||
EtherInt(const std::string &name)
|
||||
: portName(name), peer(NULL) {}
|
||||
virtual ~EtherInt() {}
|
||||
|
||||
/** Return port name (for DPRINTF). */
|
||||
const std::string &name() const { return portName; }
|
||||
|
||||
void setPeer(EtherInt *p);
|
||||
EtherInt* getPeer() { return peer; }
|
||||
|
||||
void recvDone() { peer->sendDone(); }
|
||||
virtual void sendDone() = 0;
|
||||
|
||||
bool sendPacket(EthPacketPtr packet)
|
||||
{ return peer ? peer->recvPacket(packet) : true; }
|
||||
virtual bool recvPacket(EthPacketPtr packet) = 0;
|
||||
|
||||
bool askBusy() {return peer->isBusy(); }
|
||||
virtual bool isBusy() { return false; }
|
||||
};
|
||||
|
||||
#endif // __DEV_ETHERINT_HH__
|
||||
290
simulators/gem5/src/dev/etherlink.cc
Normal file
290
simulators/gem5/src/dev/etherlink.cc
Normal file
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 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: Nathan Binkert
|
||||
* Ron Dreslinski
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* Device module for modelling a fixed bandwidth full duplex ethernet link
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/random.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/Ethernet.hh"
|
||||
#include "debug/EthernetData.hh"
|
||||
#include "dev/etherdump.hh"
|
||||
#include "dev/etherint.hh"
|
||||
#include "dev/etherlink.hh"
|
||||
#include "dev/etherpkt.hh"
|
||||
#include "params/EtherLink.hh"
|
||||
#include "sim/core.hh"
|
||||
#include "sim/serialize.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
EtherLink::EtherLink(const Params *p)
|
||||
: EtherObject(p)
|
||||
{
|
||||
link[0] = new Link(name() + ".link0", this, 0, p->speed,
|
||||
p->delay, p->delay_var, p->dump);
|
||||
link[1] = new Link(name() + ".link1", this, 1, p->speed,
|
||||
p->delay, p->delay_var, p->dump);
|
||||
|
||||
interface[0] = new Interface(name() + ".int0", link[0], link[1]);
|
||||
interface[1] = new Interface(name() + ".int1", link[1], link[0]);
|
||||
}
|
||||
|
||||
|
||||
EtherLink::~EtherLink()
|
||||
{
|
||||
delete link[0];
|
||||
delete link[1];
|
||||
|
||||
delete interface[0];
|
||||
delete interface[1];
|
||||
}
|
||||
|
||||
EtherInt*
|
||||
EtherLink::getEthPort(const std::string &if_name, int idx)
|
||||
{
|
||||
Interface *i;
|
||||
if (if_name == "int0")
|
||||
i = interface[0];
|
||||
else if (if_name == "int1")
|
||||
i = interface[1];
|
||||
else
|
||||
return NULL;
|
||||
if (i->getPeer())
|
||||
panic("interface already connected to\n");
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
|
||||
: EtherInt(name), txlink(tx)
|
||||
{
|
||||
tx->setTxInt(this);
|
||||
rx->setRxInt(this);
|
||||
}
|
||||
|
||||
EtherLink::Link::Link(const string &name, EtherLink *p, int num,
|
||||
double rate, Tick delay, Tick delay_var, EtherDump *d)
|
||||
: objName(name), parent(p), number(num), txint(NULL), rxint(NULL),
|
||||
ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d),
|
||||
doneEvent(this)
|
||||
{ }
|
||||
|
||||
void
|
||||
EtherLink::serialize(ostream &os)
|
||||
{
|
||||
link[0]->serialize("link0", os);
|
||||
link[1]->serialize("link1", os);
|
||||
}
|
||||
|
||||
void
|
||||
EtherLink::unserialize(Checkpoint *cp, const string §ion)
|
||||
{
|
||||
link[0]->unserialize("link0", cp, section);
|
||||
link[1]->unserialize("link1", cp, section);
|
||||
}
|
||||
|
||||
void
|
||||
EtherLink::Link::txComplete(EthPacketPtr packet)
|
||||
{
|
||||
DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
|
||||
DDUMP(EthernetData, packet->data, packet->length);
|
||||
rxint->sendPacket(packet);
|
||||
}
|
||||
|
||||
class LinkDelayEvent : public Event
|
||||
{
|
||||
protected:
|
||||
EtherLink::Link *link;
|
||||
EthPacketPtr packet;
|
||||
|
||||
public:
|
||||
// non-scheduling version for createForUnserialize()
|
||||
LinkDelayEvent();
|
||||
LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt);
|
||||
|
||||
void process();
|
||||
|
||||
virtual void serialize(ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const string §ion);
|
||||
static Serializable *createForUnserialize(Checkpoint *cp,
|
||||
const string §ion);
|
||||
};
|
||||
|
||||
void
|
||||
EtherLink::Link::txDone()
|
||||
{
|
||||
if (dump)
|
||||
dump->dump(packet);
|
||||
|
||||
if (linkDelay > 0) {
|
||||
DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay);
|
||||
Event *event = new LinkDelayEvent(this, packet);
|
||||
parent->schedule(event, curTick() + linkDelay);
|
||||
} else {
|
||||
txComplete(packet);
|
||||
}
|
||||
|
||||
packet = 0;
|
||||
assert(!busy());
|
||||
|
||||
txint->sendDone();
|
||||
}
|
||||
|
||||
bool
|
||||
EtherLink::Link::transmit(EthPacketPtr pkt)
|
||||
{
|
||||
if (busy()) {
|
||||
DPRINTF(Ethernet, "packet not sent, link busy\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length);
|
||||
DDUMP(EthernetData, pkt->data, pkt->length);
|
||||
|
||||
packet = pkt;
|
||||
Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
|
||||
if (delayVar != 0)
|
||||
delay += random_mt.random<Tick>(0, delayVar);
|
||||
|
||||
DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
|
||||
delay, ticksPerByte);
|
||||
parent->schedule(doneEvent, curTick() + delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
EtherLink::Link::serialize(const string &base, ostream &os)
|
||||
{
|
||||
bool packet_exists = packet;
|
||||
paramOut(os, base + ".packet_exists", packet_exists);
|
||||
if (packet_exists)
|
||||
packet->serialize(base + ".packet", os);
|
||||
|
||||
bool event_scheduled = doneEvent.scheduled();
|
||||
paramOut(os, base + ".event_scheduled", event_scheduled);
|
||||
if (event_scheduled) {
|
||||
Tick event_time = doneEvent.when();
|
||||
paramOut(os, base + ".event_time", event_time);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
EtherLink::Link::unserialize(const string &base, Checkpoint *cp,
|
||||
const string §ion)
|
||||
{
|
||||
bool packet_exists;
|
||||
paramIn(cp, section, base + ".packet_exists", packet_exists);
|
||||
if (packet_exists) {
|
||||
packet = new EthPacketData(16384);
|
||||
packet->unserialize(base + ".packet", cp, section);
|
||||
}
|
||||
|
||||
bool event_scheduled;
|
||||
paramIn(cp, section, base + ".event_scheduled", event_scheduled);
|
||||
if (event_scheduled) {
|
||||
Tick event_time;
|
||||
paramIn(cp, section, base + ".event_time", event_time);
|
||||
parent->schedule(doneEvent, event_time);
|
||||
}
|
||||
}
|
||||
|
||||
LinkDelayEvent::LinkDelayEvent()
|
||||
: Event(Default_Pri, AutoSerialize | AutoDelete), link(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p)
|
||||
: Event(Default_Pri, AutoSerialize | AutoDelete), link(l), packet(p)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LinkDelayEvent::process()
|
||||
{
|
||||
link->txComplete(packet);
|
||||
}
|
||||
|
||||
void
|
||||
LinkDelayEvent::serialize(ostream &os)
|
||||
{
|
||||
paramOut(os, "type", string("LinkDelayEvent"));
|
||||
Event::serialize(os);
|
||||
|
||||
EtherLink *parent = link->parent;
|
||||
bool number = link->number;
|
||||
SERIALIZE_OBJPTR(parent);
|
||||
SERIALIZE_SCALAR(number);
|
||||
|
||||
packet->serialize("packet", os);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion)
|
||||
{
|
||||
Event::unserialize(cp, section);
|
||||
|
||||
EtherLink *parent;
|
||||
bool number;
|
||||
UNSERIALIZE_OBJPTR(parent);
|
||||
UNSERIALIZE_SCALAR(number);
|
||||
|
||||
link = parent->link[number];
|
||||
|
||||
packet = new EthPacketData(16384);
|
||||
packet->unserialize("packet", cp, section);
|
||||
}
|
||||
|
||||
|
||||
Serializable *
|
||||
LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion)
|
||||
{
|
||||
return new LinkDelayEvent();
|
||||
}
|
||||
|
||||
REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
|
||||
|
||||
EtherLink *
|
||||
EtherLinkParams::create()
|
||||
{
|
||||
return new EtherLink(this);
|
||||
}
|
||||
143
simulators/gem5/src/dev/etherlink.hh
Normal file
143
simulators/gem5/src/dev/etherlink.hh
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* Device module for modelling a fixed bandwidth full duplex ethernet link
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ETHERLINK_HH__
|
||||
#define __DEV_ETHERLINK_HH__
|
||||
|
||||
#include "base/types.hh"
|
||||
#include "dev/etherint.hh"
|
||||
#include "dev/etherobject.hh"
|
||||
#include "dev/etherpkt.hh"
|
||||
#include "params/EtherLink.hh"
|
||||
#include "sim/eventq.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
class EtherDump;
|
||||
class Checkpoint;
|
||||
/*
|
||||
* Model for a fixed bandwidth full duplex ethernet link
|
||||
*/
|
||||
class EtherLink : public EtherObject
|
||||
{
|
||||
protected:
|
||||
class Interface;
|
||||
|
||||
friend class LinkDelayEvent;
|
||||
/*
|
||||
* Model for a single uni-directional link
|
||||
*/
|
||||
class Link
|
||||
{
|
||||
protected:
|
||||
std::string objName;
|
||||
|
||||
EtherLink *parent;
|
||||
int number;
|
||||
|
||||
Interface *txint;
|
||||
Interface *rxint;
|
||||
|
||||
double ticksPerByte;
|
||||
Tick linkDelay;
|
||||
Tick delayVar;
|
||||
EtherDump *dump;
|
||||
|
||||
protected:
|
||||
/*
|
||||
* Transfer is complete
|
||||
*/
|
||||
EthPacketPtr packet;
|
||||
void txDone();
|
||||
typedef EventWrapper<Link, &Link::txDone> DoneEvent;
|
||||
friend void DoneEvent::process();
|
||||
DoneEvent doneEvent;
|
||||
|
||||
friend class LinkDelayEvent;
|
||||
void txComplete(EthPacketPtr packet);
|
||||
|
||||
public:
|
||||
Link(const std::string &name, EtherLink *p, int num,
|
||||
double rate, Tick delay, Tick delay_var, EtherDump *dump);
|
||||
~Link() {}
|
||||
|
||||
const std::string name() const { return objName; }
|
||||
|
||||
bool busy() const { return (bool)packet; }
|
||||
bool transmit(EthPacketPtr packet);
|
||||
|
||||
void setTxInt(Interface *i) { assert(!txint); txint = i; }
|
||||
void setRxInt(Interface *i) { assert(!rxint); rxint = i; }
|
||||
|
||||
void serialize(const std::string &base, std::ostream &os);
|
||||
void unserialize(const std::string &base, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
};
|
||||
|
||||
/*
|
||||
* Interface at each end of the link
|
||||
*/
|
||||
class Interface : public EtherInt
|
||||
{
|
||||
private:
|
||||
Link *txlink;
|
||||
|
||||
public:
|
||||
Interface(const std::string &name, Link *txlink, Link *rxlink);
|
||||
bool recvPacket(EthPacketPtr packet) { return txlink->transmit(packet); }
|
||||
void sendDone() { peer->sendDone(); }
|
||||
bool isBusy() { return txlink->busy(); }
|
||||
};
|
||||
|
||||
Link *link[2];
|
||||
Interface *interface[2];
|
||||
|
||||
public:
|
||||
typedef EtherLinkParams Params;
|
||||
EtherLink(const Params *p);
|
||||
virtual ~EtherLink();
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
virtual EtherInt *getEthPort(const std::string &if_name, int idx);
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
};
|
||||
|
||||
#endif // __ETHERLINK_HH__
|
||||
67
simulators/gem5/src/dev/etherobject.hh
Normal file
67
simulators/gem5/src/dev/etherobject.hh
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2007 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
|
||||
* Base Ethernet Object declaration.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ETHEROBJECT_HH__
|
||||
#define __DEV_ETHEROBJECT_HH__
|
||||
|
||||
#include "params/EtherObject.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
class EtherInt;
|
||||
|
||||
/**
|
||||
* The base EtherObject class, allows for an accesor function to a
|
||||
* simobj that returns the Port.
|
||||
*/
|
||||
class EtherObject : public SimObject
|
||||
{
|
||||
public:
|
||||
typedef EtherObjectParams Params;
|
||||
EtherObject(const Params *params)
|
||||
: SimObject(params) {}
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
public:
|
||||
/** Additional function to return the Port of a memory object. */
|
||||
virtual EtherInt *getEthPort(const std::string &if_name, int idx = -1) = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif //__MEM_MEM_OBJECT_HH__
|
||||
53
simulators/gem5/src/dev/etherpkt.cc
Normal file
53
simulators/gem5/src/dev/etherpkt.cc
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "base/misc.hh"
|
||||
#include "dev/etherpkt.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void
|
||||
EthPacketData::serialize(const string &base, ostream &os)
|
||||
{
|
||||
paramOut(os, base + ".length", length);
|
||||
arrayParamOut(os, base + ".data", data, length);
|
||||
}
|
||||
|
||||
void
|
||||
EthPacketData::unserialize(const string &base, Checkpoint *cp,
|
||||
const string §ion)
|
||||
{
|
||||
paramIn(cp, section, base + ".length", length);
|
||||
if (length)
|
||||
arrayParamIn(cp, section, base + ".data", data, length);
|
||||
}
|
||||
86
simulators/gem5/src/dev/etherpkt.hh
Normal file
86
simulators/gem5/src/dev/etherpkt.hh
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 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: Nathan Binkert
|
||||
* Lisa Hsu
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* Reference counted class containing ethernet packet data
|
||||
*/
|
||||
|
||||
#ifndef __ETHERPKT_HH__
|
||||
#define __ETHERPKT_HH__
|
||||
|
||||
#include <cassert>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
|
||||
#include "base/refcnt.hh"
|
||||
#include "base/types.hh"
|
||||
|
||||
/*
|
||||
* Reference counted class containing ethernet packet data
|
||||
*/
|
||||
class Checkpoint;
|
||||
class EthPacketData : public RefCounted
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Pointer to packet data will be deleted
|
||||
*/
|
||||
uint8_t *data;
|
||||
|
||||
/*
|
||||
* Length of the current packet
|
||||
*/
|
||||
unsigned length;
|
||||
|
||||
public:
|
||||
EthPacketData()
|
||||
: data(NULL), length(0)
|
||||
{ }
|
||||
|
||||
explicit EthPacketData(unsigned size)
|
||||
: data(new uint8_t[size]), length(0)
|
||||
{ }
|
||||
|
||||
EthPacketData(std::auto_ptr<uint8_t> d, int l)
|
||||
: data(d.release()), length(l)
|
||||
{ }
|
||||
|
||||
~EthPacketData() { if (data) delete [] data; }
|
||||
|
||||
public:
|
||||
void serialize(const std::string &base, std::ostream &os);
|
||||
void unserialize(const std::string &base, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
};
|
||||
|
||||
typedef RefCountingPtr<EthPacketData> EthPacketPtr;
|
||||
|
||||
#endif // __ETHERPKT_HH__
|
||||
340
simulators/gem5/src/dev/ethertap.cc
Normal file
340
simulators/gem5/src/dev/ethertap.cc
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* Interface to connect a simulated ethernet device to the real world
|
||||
*/
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__APPLE__)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
#include "base/misc.hh"
|
||||
#include "base/pollevent.hh"
|
||||
#include "base/socket.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/Ethernet.hh"
|
||||
#include "debug/EthernetData.hh"
|
||||
#include "dev/etherdump.hh"
|
||||
#include "dev/etherint.hh"
|
||||
#include "dev/etherpkt.hh"
|
||||
#include "dev/ethertap.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
*/
|
||||
class TapListener
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
*/
|
||||
class Event : public PollEvent
|
||||
{
|
||||
protected:
|
||||
TapListener *listener;
|
||||
|
||||
public:
|
||||
Event(TapListener *l, int fd, int e)
|
||||
: PollEvent(fd, e), listener(l) {}
|
||||
|
||||
virtual void process(int revent) { listener->accept(); }
|
||||
};
|
||||
|
||||
friend class Event;
|
||||
Event *event;
|
||||
|
||||
protected:
|
||||
ListenSocket listener;
|
||||
EtherTap *tap;
|
||||
int port;
|
||||
|
||||
public:
|
||||
TapListener(EtherTap *t, int p)
|
||||
: event(NULL), tap(t), port(p) {}
|
||||
~TapListener() { if (event) delete event; }
|
||||
|
||||
void accept();
|
||||
void listen();
|
||||
};
|
||||
|
||||
void
|
||||
TapListener::listen()
|
||||
{
|
||||
while (!listener.listen(port, true)) {
|
||||
DPRINTF(Ethernet, "TapListener(listen): Can't bind port %d\n", port);
|
||||
port++;
|
||||
}
|
||||
|
||||
ccprintf(cerr, "Listening for tap connection on port %d\n", port);
|
||||
event = new Event(this, listener.getfd(), POLLIN|POLLERR);
|
||||
pollQueue.schedule(event);
|
||||
}
|
||||
|
||||
void
|
||||
TapListener::accept()
|
||||
{
|
||||
if (!listener.islistening())
|
||||
panic("TapListener(accept): cannot accept if we're not listening!");
|
||||
|
||||
int sfd = listener.accept(true);
|
||||
if (sfd != -1)
|
||||
tap->attach(sfd);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
class TapEvent : public PollEvent
|
||||
{
|
||||
protected:
|
||||
EtherTap *tap;
|
||||
|
||||
public:
|
||||
TapEvent(EtherTap *_tap, int fd, int e)
|
||||
: PollEvent(fd, e), tap(_tap) {}
|
||||
virtual void process(int revent) { tap->process(revent); }
|
||||
};
|
||||
|
||||
EtherTap::EtherTap(const Params *p)
|
||||
: EtherObject(p), event(NULL), socket(-1), buflen(p->bufsz), dump(p->dump),
|
||||
interface(NULL), txEvent(this)
|
||||
{
|
||||
if (ListenSocket::allDisabled())
|
||||
fatal("All listeners are disabled! EtherTap can't work!");
|
||||
|
||||
buffer = new char[buflen];
|
||||
listener = new TapListener(this, p->port);
|
||||
listener->listen();
|
||||
interface = new EtherTapInt(name() + ".interface", this);
|
||||
}
|
||||
|
||||
EtherTap::~EtherTap()
|
||||
{
|
||||
if (event)
|
||||
delete event;
|
||||
if (buffer)
|
||||
delete [] buffer;
|
||||
|
||||
delete listener;
|
||||
}
|
||||
|
||||
void
|
||||
EtherTap::attach(int fd)
|
||||
{
|
||||
if (socket != -1)
|
||||
close(fd);
|
||||
|
||||
buffer_offset = 0;
|
||||
data_len = 0;
|
||||
socket = fd;
|
||||
DPRINTF(Ethernet, "EtherTap attached\n");
|
||||
event = new TapEvent(this, socket, POLLIN|POLLERR);
|
||||
pollQueue.schedule(event);
|
||||
}
|
||||
|
||||
void
|
||||
EtherTap::detach()
|
||||
{
|
||||
DPRINTF(Ethernet, "EtherTap detached\n");
|
||||
delete event;
|
||||
event = 0;
|
||||
close(socket);
|
||||
socket = -1;
|
||||
}
|
||||
|
||||
bool
|
||||
EtherTap::recvPacket(EthPacketPtr packet)
|
||||
{
|
||||
if (dump)
|
||||
dump->dump(packet);
|
||||
|
||||
DPRINTF(Ethernet, "EtherTap output len=%d\n", packet->length);
|
||||
DDUMP(EthernetData, packet->data, packet->length);
|
||||
uint32_t len = htonl(packet->length);
|
||||
ssize_t ret = write(socket, &len, sizeof(len));
|
||||
if (ret != sizeof(len))
|
||||
return false;
|
||||
ret = write(socket, packet->data, packet->length);
|
||||
if (ret != packet->length)
|
||||
return false;
|
||||
|
||||
interface->recvDone();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
EtherTap::sendDone()
|
||||
{}
|
||||
|
||||
void
|
||||
EtherTap::process(int revent)
|
||||
{
|
||||
if (revent & POLLERR) {
|
||||
detach();
|
||||
return;
|
||||
}
|
||||
|
||||
char *data = buffer + sizeof(uint32_t);
|
||||
if (!(revent & POLLIN))
|
||||
return;
|
||||
|
||||
if (buffer_offset < data_len + sizeof(uint32_t)) {
|
||||
int len = read(socket, buffer + buffer_offset, buflen - buffer_offset);
|
||||
if (len == 0) {
|
||||
detach();
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_offset += len;
|
||||
|
||||
if (data_len == 0)
|
||||
data_len = ntohl(*(uint32_t *)buffer);
|
||||
|
||||
DPRINTF(Ethernet, "Received data from peer: len=%d buffer_offset=%d "
|
||||
"data_len=%d\n", len, buffer_offset, data_len);
|
||||
}
|
||||
|
||||
while (data_len != 0 && buffer_offset >= data_len + sizeof(uint32_t)) {
|
||||
EthPacketPtr packet;
|
||||
packet = new EthPacketData(data_len);
|
||||
packet->length = data_len;
|
||||
memcpy(packet->data, data, data_len);
|
||||
|
||||
buffer_offset -= data_len + sizeof(uint32_t);
|
||||
assert(buffer_offset >= 0);
|
||||
if (buffer_offset > 0) {
|
||||
memmove(buffer, data + data_len, buffer_offset);
|
||||
data_len = ntohl(*(uint32_t *)buffer);
|
||||
} else
|
||||
data_len = 0;
|
||||
|
||||
DPRINTF(Ethernet, "EtherTap input len=%d\n", packet->length);
|
||||
DDUMP(EthernetData, packet->data, packet->length);
|
||||
if (!interface->sendPacket(packet)) {
|
||||
DPRINTF(Ethernet, "bus busy...buffer for retransmission\n");
|
||||
packetBuffer.push(packet);
|
||||
if (!txEvent.scheduled())
|
||||
schedule(txEvent, curTick() + retryTime);
|
||||
} else if (dump) {
|
||||
dump->dump(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EtherTap::retransmit()
|
||||
{
|
||||
if (packetBuffer.empty())
|
||||
return;
|
||||
|
||||
EthPacketPtr packet = packetBuffer.front();
|
||||
if (interface->sendPacket(packet)) {
|
||||
if (dump)
|
||||
dump->dump(packet);
|
||||
DPRINTF(Ethernet, "EtherTap retransmit\n");
|
||||
packetBuffer.front() = NULL;
|
||||
packetBuffer.pop();
|
||||
}
|
||||
|
||||
if (!packetBuffer.empty() && !txEvent.scheduled())
|
||||
schedule(txEvent, curTick() + retryTime);
|
||||
}
|
||||
|
||||
EtherInt*
|
||||
EtherTap::getEthPort(const std::string &if_name, int idx)
|
||||
{
|
||||
if (if_name == "tap") {
|
||||
if (interface->getPeer())
|
||||
panic("Interface already connected to\n");
|
||||
return interface;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================
|
||||
|
||||
void
|
||||
EtherTap::serialize(ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(socket);
|
||||
SERIALIZE_SCALAR(buflen);
|
||||
uint8_t *buffer = (uint8_t *)this->buffer;
|
||||
SERIALIZE_ARRAY(buffer, buflen);
|
||||
SERIALIZE_SCALAR(buffer_offset);
|
||||
SERIALIZE_SCALAR(data_len);
|
||||
|
||||
bool tapevent_present = false;
|
||||
if (event) {
|
||||
tapevent_present = true;
|
||||
SERIALIZE_SCALAR(tapevent_present);
|
||||
event->serialize(os);
|
||||
}
|
||||
else {
|
||||
SERIALIZE_SCALAR(tapevent_present);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EtherTap::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(socket);
|
||||
UNSERIALIZE_SCALAR(buflen);
|
||||
uint8_t *buffer = (uint8_t *)this->buffer;
|
||||
UNSERIALIZE_ARRAY(buffer, buflen);
|
||||
UNSERIALIZE_SCALAR(buffer_offset);
|
||||
UNSERIALIZE_SCALAR(data_len);
|
||||
|
||||
bool tapevent_present;
|
||||
UNSERIALIZE_SCALAR(tapevent_present);
|
||||
if (tapevent_present) {
|
||||
event = new TapEvent(this, socket, POLLIN|POLLERR);
|
||||
|
||||
event->unserialize(cp,section);
|
||||
|
||||
if (event->queued()) {
|
||||
pollQueue.schedule(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
|
||||
EtherTap *
|
||||
EtherTapParams::create()
|
||||
{
|
||||
return new EtherTap(this);
|
||||
}
|
||||
136
simulators/gem5/src/dev/ethertap.hh
Normal file
136
simulators/gem5/src/dev/ethertap.hh
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* Interface to connect a simulated ethernet device to the real world
|
||||
*/
|
||||
|
||||
#ifndef __ETHERTAP_HH__
|
||||
#define __ETHERTAP_HH__
|
||||
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
#include "base/pollevent.hh"
|
||||
#include "dev/etherint.hh"
|
||||
#include "dev/etherobject.hh"
|
||||
#include "dev/etherpkt.hh"
|
||||
#include "params/EtherTap.hh"
|
||||
#include "sim/eventq.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
class TapEvent;
|
||||
class TapListener;
|
||||
class EtherTapInt;
|
||||
|
||||
/*
|
||||
* Interface to connect a simulated ethernet device to the real world
|
||||
*/
|
||||
class EtherTap : public EtherObject
|
||||
{
|
||||
protected:
|
||||
friend class TapEvent;
|
||||
TapEvent *event;
|
||||
|
||||
protected:
|
||||
friend class TapListener;
|
||||
TapListener *listener;
|
||||
int socket;
|
||||
char *buffer;
|
||||
int buflen;
|
||||
uint32_t buffer_offset;
|
||||
uint32_t data_len;
|
||||
|
||||
EtherDump *dump;
|
||||
|
||||
void attach(int fd);
|
||||
void detach();
|
||||
|
||||
protected:
|
||||
std::string device;
|
||||
std::queue<EthPacketPtr> packetBuffer;
|
||||
EtherTapInt *interface;
|
||||
|
||||
void process(int revent);
|
||||
void enqueue(EthPacketData *packet);
|
||||
void retransmit();
|
||||
|
||||
/*
|
||||
*/
|
||||
class TxEvent : public Event
|
||||
{
|
||||
protected:
|
||||
EtherTap *tap;
|
||||
|
||||
public:
|
||||
TxEvent(EtherTap *_tap) : tap(_tap) {}
|
||||
void process() { tap->retransmit(); }
|
||||
virtual const char *description() const
|
||||
{ return "EtherTap retransmit"; }
|
||||
};
|
||||
|
||||
friend class TxEvent;
|
||||
TxEvent txEvent;
|
||||
|
||||
public:
|
||||
typedef EtherTapParams Params;
|
||||
EtherTap(const Params *p);
|
||||
virtual ~EtherTap();
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
virtual EtherInt *getEthPort(const std::string &if_name, int idx);
|
||||
|
||||
virtual bool recvPacket(EthPacketPtr packet);
|
||||
virtual void sendDone();
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
class EtherTapInt : public EtherInt
|
||||
{
|
||||
private:
|
||||
EtherTap *tap;
|
||||
public:
|
||||
EtherTapInt(const std::string &name, EtherTap *t)
|
||||
: EtherInt(name), tap(t)
|
||||
{ }
|
||||
|
||||
virtual bool recvPacket(EthPacketPtr pkt) { return tap->recvPacket(pkt); }
|
||||
virtual void sendDone() { tap->sendDone(); }
|
||||
};
|
||||
|
||||
|
||||
#endif // __ETHERTAP_HH__
|
||||
2563
simulators/gem5/src/dev/i8254xGBe.cc
Normal file
2563
simulators/gem5/src/dev/i8254xGBe.cc
Normal file
File diff suppressed because it is too large
Load Diff
559
simulators/gem5/src/dev/i8254xGBe.hh
Normal file
559
simulators/gem5/src/dev/i8254xGBe.hh
Normal file
@ -0,0 +1,559 @@
|
||||
/*
|
||||
* 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
|
||||
* Device model for Intel's 8254x line of gigabit ethernet controllers.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_I8254XGBE_HH__
|
||||
#define __DEV_I8254XGBE_HH__
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
#include "base/cp_annotate.hh"
|
||||
#include "base/inet.hh"
|
||||
#include "debug/EthernetDesc.hh"
|
||||
#include "debug/EthernetIntr.hh"
|
||||
#include "dev/etherdevice.hh"
|
||||
#include "dev/etherint.hh"
|
||||
#include "dev/etherpkt.hh"
|
||||
#include "dev/i8254xGBe_defs.hh"
|
||||
#include "dev/pcidev.hh"
|
||||
#include "dev/pktfifo.hh"
|
||||
#include "params/IGbE.hh"
|
||||
#include "sim/eventq.hh"
|
||||
|
||||
class IGbEInt;
|
||||
|
||||
class IGbE : public EtherDevice
|
||||
{
|
||||
private:
|
||||
IGbEInt *etherInt;
|
||||
CPA *cpa;
|
||||
|
||||
// device registers
|
||||
iGbReg::Regs regs;
|
||||
|
||||
// eeprom data, status and control bits
|
||||
int eeOpBits, eeAddrBits, eeDataBits;
|
||||
uint8_t eeOpcode, eeAddr;
|
||||
uint16_t flash[iGbReg::EEPROM_SIZE];
|
||||
|
||||
// The drain event if we have one
|
||||
Event *drainEvent;
|
||||
|
||||
// cached parameters from params struct
|
||||
bool useFlowControl;
|
||||
|
||||
// packet fifos
|
||||
PacketFifo rxFifo;
|
||||
PacketFifo txFifo;
|
||||
|
||||
// Packet that we are currently putting into the txFifo
|
||||
EthPacketPtr txPacket;
|
||||
|
||||
// Should to Rx/Tx State machine tick?
|
||||
bool rxTick;
|
||||
bool txTick;
|
||||
bool txFifoTick;
|
||||
|
||||
bool rxDmaPacket;
|
||||
|
||||
// Number of bytes copied from current RX packet
|
||||
unsigned pktOffset;
|
||||
|
||||
// Delays in managaging descriptors
|
||||
Tick fetchDelay, wbDelay;
|
||||
Tick fetchCompDelay, wbCompDelay;
|
||||
Tick rxWriteDelay, txReadDelay;
|
||||
|
||||
// Event and function to deal with RDTR timer expiring
|
||||
void rdtrProcess() {
|
||||
rxDescCache.writeback(0);
|
||||
DPRINTF(EthernetIntr,
|
||||
"Posting RXT interrupt because RDTR timer expired\n");
|
||||
postInterrupt(iGbReg::IT_RXT);
|
||||
}
|
||||
|
||||
//friend class EventWrapper<IGbE, &IGbE::rdtrProcess>;
|
||||
EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent;
|
||||
|
||||
// Event and function to deal with RADV timer expiring
|
||||
void radvProcess() {
|
||||
rxDescCache.writeback(0);
|
||||
DPRINTF(EthernetIntr,
|
||||
"Posting RXT interrupt because RADV timer expired\n");
|
||||
postInterrupt(iGbReg::IT_RXT);
|
||||
}
|
||||
|
||||
//friend class EventWrapper<IGbE, &IGbE::radvProcess>;
|
||||
EventWrapper<IGbE, &IGbE::radvProcess> radvEvent;
|
||||
|
||||
// Event and function to deal with TADV timer expiring
|
||||
void tadvProcess() {
|
||||
txDescCache.writeback(0);
|
||||
DPRINTF(EthernetIntr,
|
||||
"Posting TXDW interrupt because TADV timer expired\n");
|
||||
postInterrupt(iGbReg::IT_TXDW);
|
||||
}
|
||||
|
||||
//friend class EventWrapper<IGbE, &IGbE::tadvProcess>;
|
||||
EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent;
|
||||
|
||||
// Event and function to deal with TIDV timer expiring
|
||||
void tidvProcess() {
|
||||
txDescCache.writeback(0);
|
||||
DPRINTF(EthernetIntr,
|
||||
"Posting TXDW interrupt because TIDV timer expired\n");
|
||||
postInterrupt(iGbReg::IT_TXDW);
|
||||
}
|
||||
//friend class EventWrapper<IGbE, &IGbE::tidvProcess>;
|
||||
EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent;
|
||||
|
||||
// Main event to tick the device
|
||||
void tick();
|
||||
//friend class EventWrapper<IGbE, &IGbE::tick>;
|
||||
EventWrapper<IGbE, &IGbE::tick> tickEvent;
|
||||
|
||||
|
||||
uint64_t macAddr;
|
||||
|
||||
void rxStateMachine();
|
||||
void txStateMachine();
|
||||
void txWire();
|
||||
|
||||
/** Write an interrupt into the interrupt pending register and check mask
|
||||
* and interrupt limit timer before sending interrupt to CPU
|
||||
* @param t the type of interrupt we are posting
|
||||
* @param now should we ignore the interrupt limiting timer
|
||||
*/
|
||||
void postInterrupt(iGbReg::IntTypes t, bool now = false);
|
||||
|
||||
/** Check and see if changes to the mask register have caused an interrupt
|
||||
* to need to be sent or perhaps removed an interrupt cause.
|
||||
*/
|
||||
void chkInterrupt();
|
||||
|
||||
/** Send an interrupt to the cpu
|
||||
*/
|
||||
void delayIntEvent();
|
||||
void cpuPostInt();
|
||||
// Event to moderate interrupts
|
||||
EventWrapper<IGbE, &IGbE::delayIntEvent> interEvent;
|
||||
|
||||
/** Clear the interupt line to the cpu
|
||||
*/
|
||||
void cpuClearInt();
|
||||
|
||||
Tick intClock() { return SimClock::Int::ns * 1024; }
|
||||
|
||||
/** This function is used to restart the clock so it can handle things like
|
||||
* draining and resume in one place. */
|
||||
void restartClock();
|
||||
|
||||
/** Check if all the draining things that need to occur have occured and
|
||||
* handle the drain event if so.
|
||||
*/
|
||||
void checkDrain();
|
||||
|
||||
void anBegin(std::string sm, std::string st, int flags = CPA::FL_NONE) {
|
||||
cpa->hwBegin((CPA::flags)flags, sys, macAddr, sm, st);
|
||||
}
|
||||
|
||||
void anQ(std::string sm, std::string q) {
|
||||
cpa->hwQ(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
|
||||
}
|
||||
|
||||
void anDq(std::string sm, std::string q) {
|
||||
cpa->hwDq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
|
||||
}
|
||||
|
||||
void anPq(std::string sm, std::string q, int num = 1) {
|
||||
cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num);
|
||||
}
|
||||
|
||||
void anRq(std::string sm, std::string q, int num = 1) {
|
||||
cpa->hwRq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num);
|
||||
}
|
||||
|
||||
void anWe(std::string sm, std::string q) {
|
||||
cpa->hwWe(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
|
||||
}
|
||||
|
||||
void anWf(std::string sm, std::string q) {
|
||||
cpa->hwWf(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
class DescCache
|
||||
{
|
||||
protected:
|
||||
virtual Addr descBase() const = 0;
|
||||
virtual long descHead() const = 0;
|
||||
virtual long descTail() const = 0;
|
||||
virtual long descLen() const = 0;
|
||||
virtual void updateHead(long h) = 0;
|
||||
virtual void enableSm() = 0;
|
||||
virtual void actionAfterWb() {}
|
||||
virtual void fetchAfterWb() = 0;
|
||||
|
||||
typedef std::deque<T *> CacheType;
|
||||
CacheType usedCache;
|
||||
CacheType unusedCache;
|
||||
|
||||
T *fetchBuf;
|
||||
T *wbBuf;
|
||||
|
||||
// Pointer to the device we cache for
|
||||
IGbE *igbe;
|
||||
|
||||
// Name of this descriptor cache
|
||||
std::string _name;
|
||||
|
||||
// How far we've cached
|
||||
int cachePnt;
|
||||
|
||||
// The size of the descriptor cache
|
||||
int size;
|
||||
|
||||
// How many descriptors we are currently fetching
|
||||
int curFetching;
|
||||
|
||||
// How many descriptors we are currently writing back
|
||||
int wbOut;
|
||||
|
||||
// if the we wrote back to the end of the descriptor ring and are going
|
||||
// to have to wrap and write more
|
||||
bool moreToWb;
|
||||
|
||||
// What the alignment is of the next descriptor writeback
|
||||
Addr wbAlignment;
|
||||
|
||||
/** The packet that is currently being dmad to memory if any */
|
||||
EthPacketPtr pktPtr;
|
||||
|
||||
/** Shortcut for DMA address translation */
|
||||
Addr pciToDma(Addr a) { return igbe->platform->pciToDma(a); }
|
||||
|
||||
public:
|
||||
/** Annotate sm*/
|
||||
std::string annSmFetch, annSmWb, annUnusedDescQ, annUsedCacheQ,
|
||||
annUsedDescQ, annUnusedCacheQ, annDescQ;
|
||||
|
||||
DescCache(IGbE *i, const std::string n, int s);
|
||||
virtual ~DescCache();
|
||||
|
||||
std::string name() { return _name; }
|
||||
|
||||
/** If the address/len/head change when we've got descriptors that are
|
||||
* dirty that is very bad. This function checks that we don't and if we
|
||||
* do panics.
|
||||
*/
|
||||
void areaChanged();
|
||||
|
||||
void writeback(Addr aMask);
|
||||
void writeback1();
|
||||
EventWrapper<DescCache, &DescCache::writeback1> wbDelayEvent;
|
||||
|
||||
/** Fetch a chunk of descriptors into the descriptor cache.
|
||||
* Calls fetchComplete when the memory system returns the data
|
||||
*/
|
||||
void fetchDescriptors();
|
||||
void fetchDescriptors1();
|
||||
EventWrapper<DescCache, &DescCache::fetchDescriptors1> fetchDelayEvent;
|
||||
|
||||
/** Called by event when dma to read descriptors is completed
|
||||
*/
|
||||
void fetchComplete();
|
||||
EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent;
|
||||
|
||||
/** Called by event when dma to writeback descriptors is completed
|
||||
*/
|
||||
void wbComplete();
|
||||
EventWrapper<DescCache, &DescCache::wbComplete> wbEvent;
|
||||
|
||||
/* Return the number of descriptors left in the ring, so the device has
|
||||
* a way to figure out if it needs to interrupt.
|
||||
*/
|
||||
unsigned
|
||||
descLeft() const
|
||||
{
|
||||
unsigned left = unusedCache.size();
|
||||
if (cachePnt > descTail())
|
||||
left += (descLen() - cachePnt + descTail());
|
||||
else
|
||||
left += (descTail() - cachePnt);
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
/* Return the number of descriptors used and not written back.
|
||||
*/
|
||||
unsigned descUsed() const { return usedCache.size(); }
|
||||
|
||||
/* Return the number of cache unused descriptors we have. */
|
||||
unsigned descUnused() const { return unusedCache.size(); }
|
||||
|
||||
/* Get into a state where the descriptor address/head/etc colud be
|
||||
* changed */
|
||||
void reset();
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
virtual bool hasOutstandingEvents() {
|
||||
return wbEvent.scheduled() || fetchEvent.scheduled();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class RxDescCache : public DescCache<iGbReg::RxDesc>
|
||||
{
|
||||
protected:
|
||||
virtual Addr descBase() const { return igbe->regs.rdba(); }
|
||||
virtual long descHead() const { return igbe->regs.rdh(); }
|
||||
virtual long descLen() const { return igbe->regs.rdlen() >> 4; }
|
||||
virtual long descTail() const { return igbe->regs.rdt(); }
|
||||
virtual void updateHead(long h) { igbe->regs.rdh(h); }
|
||||
virtual void enableSm();
|
||||
virtual void fetchAfterWb() {
|
||||
if (!igbe->rxTick && igbe->getState() == SimObject::Running)
|
||||
fetchDescriptors();
|
||||
}
|
||||
|
||||
bool pktDone;
|
||||
|
||||
/** Variable to head with header/data completion events */
|
||||
int splitCount;
|
||||
|
||||
/** Bytes of packet that have been copied, so we know when to
|
||||
set EOP */
|
||||
unsigned bytesCopied;
|
||||
|
||||
public:
|
||||
RxDescCache(IGbE *i, std::string n, int s);
|
||||
|
||||
/** Write the given packet into the buffer(s) pointed to by the
|
||||
* descriptor and update the book keeping. Should only be called when
|
||||
* there are no dma's pending.
|
||||
* @param packet ethernet packet to write
|
||||
* @param pkt_offset bytes already copied from the packet to memory
|
||||
* @return pkt_offset + number of bytes copied during this call
|
||||
*/
|
||||
int writePacket(EthPacketPtr packet, int pkt_offset);
|
||||
|
||||
/** Called by event when dma to write packet is completed
|
||||
*/
|
||||
void pktComplete();
|
||||
|
||||
/** Check if the dma on the packet has completed and RX state machine
|
||||
* can continue
|
||||
*/
|
||||
bool packetDone();
|
||||
|
||||
EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent;
|
||||
|
||||
// Event to handle issuing header and data write at the same time
|
||||
// and only callking pktComplete() when both are completed
|
||||
void pktSplitDone();
|
||||
EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktHdrEvent;
|
||||
EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktDataEvent;
|
||||
|
||||
virtual bool hasOutstandingEvents();
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
friend class RxDescCache;
|
||||
|
||||
RxDescCache rxDescCache;
|
||||
|
||||
class TxDescCache : public DescCache<iGbReg::TxDesc>
|
||||
{
|
||||
protected:
|
||||
virtual Addr descBase() const { return igbe->regs.tdba(); }
|
||||
virtual long descHead() const { return igbe->regs.tdh(); }
|
||||
virtual long descTail() const { return igbe->regs.tdt(); }
|
||||
virtual long descLen() const { return igbe->regs.tdlen() >> 4; }
|
||||
virtual void updateHead(long h) { igbe->regs.tdh(h); }
|
||||
virtual void enableSm();
|
||||
virtual void actionAfterWb();
|
||||
virtual void fetchAfterWb() {
|
||||
if (!igbe->txTick && igbe->getState() == SimObject::Running)
|
||||
fetchDescriptors();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool pktDone;
|
||||
bool isTcp;
|
||||
bool pktWaiting;
|
||||
bool pktMultiDesc;
|
||||
Addr completionAddress;
|
||||
bool completionEnabled;
|
||||
uint32_t descEnd;
|
||||
|
||||
|
||||
// tso variables
|
||||
bool useTso;
|
||||
Addr tsoHeaderLen;
|
||||
Addr tsoMss;
|
||||
Addr tsoTotalLen;
|
||||
Addr tsoUsedLen;
|
||||
Addr tsoPrevSeq;
|
||||
Addr tsoPktPayloadBytes;
|
||||
bool tsoLoadedHeader;
|
||||
bool tsoPktHasHeader;
|
||||
uint8_t tsoHeader[256];
|
||||
Addr tsoDescBytesUsed;
|
||||
Addr tsoCopyBytes;
|
||||
int tsoPkts;
|
||||
|
||||
public:
|
||||
TxDescCache(IGbE *i, std::string n, int s);
|
||||
|
||||
/** Tell the cache to DMA a packet from main memory into its buffer and
|
||||
* return the size the of the packet to reserve space in tx fifo.
|
||||
* @return size of the packet
|
||||
*/
|
||||
unsigned getPacketSize(EthPacketPtr p);
|
||||
void getPacketData(EthPacketPtr p);
|
||||
void processContextDesc();
|
||||
|
||||
/** Return the number of dsecriptors in a cache block for threshold
|
||||
* operations.
|
||||
*/
|
||||
unsigned
|
||||
descInBlock(unsigned num_desc)
|
||||
{
|
||||
return num_desc / igbe->cacheBlockSize() / sizeof(iGbReg::TxDesc);
|
||||
}
|
||||
|
||||
/** Ask if the packet has been transfered so the state machine can give
|
||||
* it to the fifo.
|
||||
* @return packet available in descriptor cache
|
||||
*/
|
||||
bool packetAvailable();
|
||||
|
||||
/** Ask if we are still waiting for the packet to be transfered.
|
||||
* @return packet still in transit.
|
||||
*/
|
||||
bool packetWaiting() { return pktWaiting; }
|
||||
|
||||
/** Ask if this packet is composed of multiple descriptors
|
||||
* so even if we've got data, we need to wait for more before
|
||||
* we can send it out.
|
||||
* @return packet can't be sent out because it's a multi-descriptor
|
||||
* packet
|
||||
*/
|
||||
bool packetMultiDesc() { return pktMultiDesc;}
|
||||
|
||||
/** Called by event when dma to write packet is completed
|
||||
*/
|
||||
void pktComplete();
|
||||
EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent;
|
||||
|
||||
void headerComplete();
|
||||
EventWrapper<TxDescCache, &TxDescCache::headerComplete> headerEvent;
|
||||
|
||||
|
||||
void completionWriteback(Addr a, bool enabled) {
|
||||
DPRINTF(EthernetDesc,
|
||||
"Completion writeback Addr: %#x enabled: %d\n",
|
||||
a, enabled);
|
||||
completionAddress = a;
|
||||
completionEnabled = enabled;
|
||||
}
|
||||
|
||||
virtual bool hasOutstandingEvents();
|
||||
|
||||
void nullCallback() {
|
||||
DPRINTF(EthernetDesc, "Completion writeback complete\n");
|
||||
}
|
||||
EventWrapper<TxDescCache, &TxDescCache::nullCallback> nullEvent;
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
};
|
||||
friend class TxDescCache;
|
||||
|
||||
TxDescCache txDescCache;
|
||||
|
||||
public:
|
||||
typedef IGbEParams Params;
|
||||
const Params *
|
||||
params() const {
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
IGbE(const Params *params);
|
||||
~IGbE() {}
|
||||
virtual void init();
|
||||
|
||||
virtual EtherInt *getEthPort(const std::string &if_name, int idx);
|
||||
|
||||
Tick clock;
|
||||
Tick lastInterrupt;
|
||||
inline Tick ticks(int numCycles) const { return numCycles * clock; }
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
virtual Tick writeConfig(PacketPtr pkt);
|
||||
|
||||
bool ethRxPkt(EthPacketPtr packet);
|
||||
void ethTxDone();
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
virtual unsigned int drain(Event *de);
|
||||
virtual void resume();
|
||||
|
||||
};
|
||||
|
||||
class IGbEInt : public EtherInt
|
||||
{
|
||||
private:
|
||||
IGbE *dev;
|
||||
|
||||
public:
|
||||
IGbEInt(const std::string &name, IGbE *d)
|
||||
: EtherInt(name), dev(d)
|
||||
{ }
|
||||
|
||||
virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); }
|
||||
virtual void sendDone() { dev->ethTxDone(); }
|
||||
};
|
||||
|
||||
#endif //__DEV_I8254XGBE_HH__
|
||||
854
simulators/gem5/src/dev/i8254xGBe_defs.hh
Normal file
854
simulators/gem5/src/dev/i8254xGBe_defs.hh
Normal file
@ -0,0 +1,854 @@
|
||||
/*
|
||||
* 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
|
||||
* Register and structure descriptions for Intel's 8254x line of gigabit ethernet controllers.
|
||||
*/
|
||||
#include "base/bitfield.hh"
|
||||
|
||||
namespace iGbReg {
|
||||
|
||||
|
||||
// Registers used by the Intel GbE NIC
|
||||
const uint32_t REG_CTRL = 0x00000;
|
||||
const uint32_t REG_STATUS = 0x00008;
|
||||
const uint32_t REG_EECD = 0x00010;
|
||||
const uint32_t REG_EERD = 0x00014;
|
||||
const uint32_t REG_CTRL_EXT = 0x00018;
|
||||
const uint32_t REG_MDIC = 0x00020;
|
||||
const uint32_t REG_FCAL = 0x00028;
|
||||
const uint32_t REG_FCAH = 0x0002C;
|
||||
const uint32_t REG_FCT = 0x00030;
|
||||
const uint32_t REG_VET = 0x00038;
|
||||
const uint32_t REG_PBA = 0x01000;
|
||||
const uint32_t REG_ICR = 0x000C0;
|
||||
const uint32_t REG_ITR = 0x000C4;
|
||||
const uint32_t REG_ICS = 0x000C8;
|
||||
const uint32_t REG_IMS = 0x000D0;
|
||||
const uint32_t REG_IMC = 0x000D8;
|
||||
const uint32_t REG_IAM = 0x000E0;
|
||||
const uint32_t REG_RCTL = 0x00100;
|
||||
const uint32_t REG_FCTTV = 0x00170;
|
||||
const uint32_t REG_TIPG = 0x00410;
|
||||
const uint32_t REG_AIFS = 0x00458;
|
||||
const uint32_t REG_LEDCTL = 0x00e00;
|
||||
const uint32_t REG_EICR = 0x01580;
|
||||
const uint32_t REG_IVAR0 = 0x01700;
|
||||
const uint32_t REG_FCRTL = 0x02160;
|
||||
const uint32_t REG_FCRTH = 0x02168;
|
||||
const uint32_t REG_RDBAL = 0x02800;
|
||||
const uint32_t REG_RDBAH = 0x02804;
|
||||
const uint32_t REG_RDLEN = 0x02808;
|
||||
const uint32_t REG_SRRCTL = 0x0280C;
|
||||
const uint32_t REG_RDH = 0x02810;
|
||||
const uint32_t REG_RDT = 0x02818;
|
||||
const uint32_t REG_RDTR = 0x02820;
|
||||
const uint32_t REG_RXDCTL = 0x02828;
|
||||
const uint32_t REG_RADV = 0x0282C;
|
||||
const uint32_t REG_TCTL = 0x00400;
|
||||
const uint32_t REG_TDBAL = 0x03800;
|
||||
const uint32_t REG_TDBAH = 0x03804;
|
||||
const uint32_t REG_TDLEN = 0x03808;
|
||||
const uint32_t REG_TDH = 0x03810;
|
||||
const uint32_t REG_TXDCA_CTL = 0x03814;
|
||||
const uint32_t REG_TDT = 0x03818;
|
||||
const uint32_t REG_TIDV = 0x03820;
|
||||
const uint32_t REG_TXDCTL = 0x03828;
|
||||
const uint32_t REG_TADV = 0x0382C;
|
||||
const uint32_t REG_TDWBAL = 0x03838;
|
||||
const uint32_t REG_TDWBAH = 0x0383C;
|
||||
const uint32_t REG_CRCERRS = 0x04000;
|
||||
const uint32_t REG_RXCSUM = 0x05000;
|
||||
const uint32_t REG_RLPML = 0x05004;
|
||||
const uint32_t REG_RFCTL = 0x05008;
|
||||
const uint32_t REG_MTA = 0x05200;
|
||||
const uint32_t REG_RAL = 0x05400;
|
||||
const uint32_t REG_RAH = 0x05404;
|
||||
const uint32_t REG_VFTA = 0x05600;
|
||||
|
||||
const uint32_t REG_WUC = 0x05800;
|
||||
const uint32_t REG_MANC = 0x05820;
|
||||
const uint32_t REG_SWSM = 0x05B50;
|
||||
const uint32_t REG_FWSM = 0x05B54;
|
||||
const uint32_t REG_SWFWSYNC = 0x05B5C;
|
||||
|
||||
const uint8_t EEPROM_READ_OPCODE_SPI = 0x03;
|
||||
const uint8_t EEPROM_RDSR_OPCODE_SPI = 0x05;
|
||||
const uint8_t EEPROM_SIZE = 64;
|
||||
const uint16_t EEPROM_CSUM = 0xBABA;
|
||||
|
||||
const uint8_t VLAN_FILTER_TABLE_SIZE = 128;
|
||||
const uint8_t RCV_ADDRESS_TABLE_SIZE = 24;
|
||||
const uint8_t MULTICAST_TABLE_SIZE = 128;
|
||||
const uint32_t STATS_REGS_SIZE = 0x228;
|
||||
|
||||
|
||||
// Registers in that are accessed in the PHY
|
||||
const uint8_t PHY_PSTATUS = 0x1;
|
||||
const uint8_t PHY_PID = 0x2;
|
||||
const uint8_t PHY_EPID = 0x3;
|
||||
const uint8_t PHY_GSTATUS = 10;
|
||||
const uint8_t PHY_EPSTATUS = 15;
|
||||
const uint8_t PHY_AGC = 18;
|
||||
|
||||
// Receive Descriptor Status Flags
|
||||
const uint16_t RXDS_DYNINT = 0x800;
|
||||
const uint16_t RXDS_UDPV = 0x400;
|
||||
const uint16_t RXDS_CRCV = 0x100;
|
||||
const uint16_t RXDS_PIF = 0x080;
|
||||
const uint16_t RXDS_IPCS = 0x040;
|
||||
const uint16_t RXDS_TCPCS = 0x020;
|
||||
const uint16_t RXDS_UDPCS = 0x010;
|
||||
const uint16_t RXDS_VP = 0x008;
|
||||
const uint16_t RXDS_IXSM = 0x004;
|
||||
const uint16_t RXDS_EOP = 0x002;
|
||||
const uint16_t RXDS_DD = 0x001;
|
||||
|
||||
// Receive Descriptor Error Flags
|
||||
const uint8_t RXDE_RXE = 0x80;
|
||||
const uint8_t RXDE_IPE = 0x40;
|
||||
const uint8_t RXDE_TCPE = 0x20;
|
||||
const uint8_t RXDE_SEQ = 0x04;
|
||||
const uint8_t RXDE_SE = 0x02;
|
||||
const uint8_t RXDE_CE = 0x01;
|
||||
|
||||
// Receive Descriptor Extended Error Flags
|
||||
const uint16_t RXDEE_HBO = 0x008;
|
||||
const uint16_t RXDEE_CE = 0x010;
|
||||
const uint16_t RXDEE_LE = 0x020;
|
||||
const uint16_t RXDEE_PE = 0x080;
|
||||
const uint16_t RXDEE_OSE = 0x100;
|
||||
const uint16_t RXDEE_USE = 0x200;
|
||||
const uint16_t RXDEE_TCPE = 0x400;
|
||||
const uint16_t RXDEE_IPE = 0x800;
|
||||
|
||||
|
||||
// Receive Descriptor Types
|
||||
const uint8_t RXDT_LEGACY = 0x00;
|
||||
const uint8_t RXDT_ADV_ONEBUF = 0x01;
|
||||
const uint8_t RXDT_ADV_SPLIT_A = 0x05;
|
||||
|
||||
// Receive Descriptor Packet Types
|
||||
const uint16_t RXDP_IPV4 = 0x001;
|
||||
const uint16_t RXDP_IPV4E = 0x002;
|
||||
const uint16_t RXDP_IPV6 = 0x004;
|
||||
const uint16_t RXDP_IPV6E = 0x008;
|
||||
const uint16_t RXDP_TCP = 0x010;
|
||||
const uint16_t RXDP_UDP = 0x020;
|
||||
const uint16_t RXDP_SCTP = 0x040;
|
||||
const uint16_t RXDP_NFS = 0x080;
|
||||
|
||||
// Interrupt types
|
||||
enum IntTypes
|
||||
{
|
||||
IT_NONE = 0x00000, //dummy value
|
||||
IT_TXDW = 0x00001,
|
||||
IT_TXQE = 0x00002,
|
||||
IT_LSC = 0x00004,
|
||||
IT_RXSEQ = 0x00008,
|
||||
IT_RXDMT = 0x00010,
|
||||
IT_RXO = 0x00040,
|
||||
IT_RXT = 0x00080,
|
||||
IT_MADC = 0x00200,
|
||||
IT_RXCFG = 0x00400,
|
||||
IT_GPI0 = 0x02000,
|
||||
IT_GPI1 = 0x04000,
|
||||
IT_TXDLOW = 0x08000,
|
||||
IT_SRPD = 0x10000,
|
||||
IT_ACK = 0x20000
|
||||
};
|
||||
|
||||
// Receive Descriptor struct
|
||||
struct RxDesc {
|
||||
union {
|
||||
struct {
|
||||
Addr buf;
|
||||
uint16_t len;
|
||||
uint16_t csum;
|
||||
uint8_t status;
|
||||
uint8_t errors;
|
||||
uint16_t vlan;
|
||||
} legacy;
|
||||
struct {
|
||||
Addr pkt;
|
||||
Addr hdr;
|
||||
} adv_read;
|
||||
struct {
|
||||
uint16_t rss_type:4;
|
||||
uint16_t pkt_type:12;
|
||||
uint16_t __reserved1:5;
|
||||
uint16_t header_len:10;
|
||||
uint16_t sph:1;
|
||||
union {
|
||||
struct {
|
||||
uint16_t id;
|
||||
uint16_t csum;
|
||||
};
|
||||
uint32_t rss_hash;
|
||||
};
|
||||
uint32_t status:20;
|
||||
uint32_t errors:12;
|
||||
uint16_t pkt_len;
|
||||
uint16_t vlan_tag;
|
||||
} adv_wb ;
|
||||
};
|
||||
};
|
||||
|
||||
struct TxDesc {
|
||||
uint64_t d1;
|
||||
uint64_t d2;
|
||||
};
|
||||
|
||||
namespace TxdOp {
|
||||
const uint8_t TXD_CNXT = 0x0;
|
||||
const uint8_t TXD_DATA = 0x1;
|
||||
const uint8_t TXD_ADVCNXT = 0x2;
|
||||
const uint8_t TXD_ADVDATA = 0x3;
|
||||
|
||||
bool isLegacy(TxDesc *d) { return !bits(d->d2,29,29); }
|
||||
uint8_t getType(TxDesc *d) { return bits(d->d2, 23,20); }
|
||||
bool isType(TxDesc *d, uint8_t type) { return getType(d) == type; }
|
||||
bool isTypes(TxDesc *d, uint8_t t1, uint8_t t2) { return isType(d, t1) || isType(d, t2); }
|
||||
bool isAdvDesc(TxDesc *d) { return !isLegacy(d) && isTypes(d, TXD_ADVDATA,TXD_ADVCNXT); }
|
||||
bool isContext(TxDesc *d) { return !isLegacy(d) && isTypes(d,TXD_CNXT, TXD_ADVCNXT); }
|
||||
bool isData(TxDesc *d) { return !isLegacy(d) && isTypes(d, TXD_DATA, TXD_ADVDATA); }
|
||||
|
||||
Addr getBuf(TxDesc *d) { assert(isLegacy(d) || isData(d)); return d->d1; }
|
||||
Addr getLen(TxDesc *d) { if (isLegacy(d)) return bits(d->d2,15,0); else return bits(d->d2, 19,0); }
|
||||
void setDd(TxDesc *d) { replaceBits(d->d2, 35, 32, ULL(1)); }
|
||||
|
||||
bool ide(TxDesc *d) { return bits(d->d2, 31,31) && (getType(d) == TXD_DATA || isLegacy(d)); }
|
||||
bool vle(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 30,30); }
|
||||
bool rs(TxDesc *d) { return bits(d->d2, 27,27); }
|
||||
bool ic(TxDesc *d) { assert(isLegacy(d) || isData(d)); return isLegacy(d) && bits(d->d2, 26,26); }
|
||||
bool tse(TxDesc *d) {
|
||||
if (isTypes(d, TXD_CNXT, TXD_DATA))
|
||||
return bits(d->d2, 26,26);
|
||||
if (isType(d, TXD_ADVDATA))
|
||||
return bits(d->d2, 31, 31);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ifcs(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 25,25); }
|
||||
bool eop(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 24,24); }
|
||||
bool ip(TxDesc *d) { assert(isContext(d)); return bits(d->d2, 25,25); }
|
||||
bool tcp(TxDesc *d) { assert(isContext(d)); return bits(d->d2, 24,24); }
|
||||
|
||||
uint8_t getCso(TxDesc *d) { assert(isLegacy(d)); return bits(d->d2, 23,16); }
|
||||
uint8_t getCss(TxDesc *d) { assert(isLegacy(d)); return bits(d->d2, 47,40); }
|
||||
|
||||
bool ixsm(TxDesc *d) { return isData(d) && bits(d->d2, 40,40); }
|
||||
bool txsm(TxDesc *d) { return isData(d) && bits(d->d2, 41,41); }
|
||||
|
||||
int tucse(TxDesc *d) { assert(isContext(d)); return bits(d->d1,63,48); }
|
||||
int tucso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,47,40); }
|
||||
int tucss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,39,32); }
|
||||
int ipcse(TxDesc *d) { assert(isContext(d)); return bits(d->d1,31,16); }
|
||||
int ipcso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,15,8); }
|
||||
int ipcss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,7,0); }
|
||||
int mss(TxDesc *d) { assert(isContext(d)); return bits(d->d2,63,48); }
|
||||
int hdrlen(TxDesc *d) {
|
||||
assert(isContext(d));
|
||||
if (!isAdvDesc(d))
|
||||
return bits(d->d2,47,40);
|
||||
return bits(d->d2, 47,40) + bits(d->d1, 8,0) + bits(d->d1, 15, 9);
|
||||
}
|
||||
|
||||
int getTsoLen(TxDesc *d) { assert(isType(d, TXD_ADVDATA)); return bits(d->d2, 63,46); }
|
||||
int utcmd(TxDesc *d) { assert(isContext(d)); return bits(d->d2,24,31); }
|
||||
} // namespace TxdOp
|
||||
|
||||
|
||||
#define ADD_FIELD32(NAME, OFFSET, BITS) \
|
||||
inline uint32_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \
|
||||
inline void NAME(uint32_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); }
|
||||
|
||||
#define ADD_FIELD64(NAME, OFFSET, BITS) \
|
||||
inline uint64_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \
|
||||
inline void NAME(uint64_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); }
|
||||
|
||||
struct Regs {
|
||||
template<class T>
|
||||
struct Reg {
|
||||
T _data;
|
||||
T operator()() { return _data; }
|
||||
const Reg<T> &operator=(T d) { _data = d; return *this;}
|
||||
bool operator==(T d) { return d == _data; }
|
||||
void operator()(T d) { _data = d; }
|
||||
Reg() { _data = 0; }
|
||||
void serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(_data);
|
||||
}
|
||||
void unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(_data);
|
||||
}
|
||||
};
|
||||
|
||||
struct CTRL : public Reg<uint32_t> { // 0x0000 CTRL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(fd,0,1); // full duplex
|
||||
ADD_FIELD32(bem,1,1); // big endian mode
|
||||
ADD_FIELD32(pcipr,2,1); // PCI priority
|
||||
ADD_FIELD32(lrst,3,1); // link reset
|
||||
ADD_FIELD32(tme,4,1); // test mode enable
|
||||
ADD_FIELD32(asde,5,1); // Auto-speed detection
|
||||
ADD_FIELD32(slu,6,1); // Set link up
|
||||
ADD_FIELD32(ilos,7,1); // invert los-of-signal
|
||||
ADD_FIELD32(speed,8,2); // speed selection bits
|
||||
ADD_FIELD32(be32,10,1); // big endian mode 32
|
||||
ADD_FIELD32(frcspd,11,1); // force speed
|
||||
ADD_FIELD32(frcdpx,12,1); // force duplex
|
||||
ADD_FIELD32(duden,13,1); // dock/undock enable
|
||||
ADD_FIELD32(dudpol,14,1); // dock/undock polarity
|
||||
ADD_FIELD32(fphyrst,15,1); // force phy reset
|
||||
ADD_FIELD32(extlen,16,1); // external link status enable
|
||||
ADD_FIELD32(rsvd,17,1); // reserved
|
||||
ADD_FIELD32(sdp0d,18,1); // software controlled pin data
|
||||
ADD_FIELD32(sdp1d,19,1); // software controlled pin data
|
||||
ADD_FIELD32(sdp2d,20,1); // software controlled pin data
|
||||
ADD_FIELD32(sdp3d,21,1); // software controlled pin data
|
||||
ADD_FIELD32(sdp0i,22,1); // software controlled pin dir
|
||||
ADD_FIELD32(sdp1i,23,1); // software controlled pin dir
|
||||
ADD_FIELD32(sdp2i,24,1); // software controlled pin dir
|
||||
ADD_FIELD32(sdp3i,25,1); // software controlled pin dir
|
||||
ADD_FIELD32(rst,26,1); // reset
|
||||
ADD_FIELD32(rfce,27,1); // receive flow control enable
|
||||
ADD_FIELD32(tfce,28,1); // transmit flow control enable
|
||||
ADD_FIELD32(rte,29,1); // routing tag enable
|
||||
ADD_FIELD32(vme,30,1); // vlan enable
|
||||
ADD_FIELD32(phyrst,31,1); // phy reset
|
||||
};
|
||||
CTRL ctrl;
|
||||
|
||||
struct STATUS : public Reg<uint32_t> { // 0x0008 STATUS Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(fd,0,1); // full duplex
|
||||
ADD_FIELD32(lu,1,1); // link up
|
||||
ADD_FIELD32(func,2,2); // function id
|
||||
ADD_FIELD32(txoff,4,1); // transmission paused
|
||||
ADD_FIELD32(tbimode,5,1); // tbi mode
|
||||
ADD_FIELD32(speed,6,2); // link speed
|
||||
ADD_FIELD32(asdv,8,2); // auto speed detection value
|
||||
ADD_FIELD32(mtxckok,10,1); // mtx clock running ok
|
||||
ADD_FIELD32(pci66,11,1); // In 66Mhz pci slot
|
||||
ADD_FIELD32(bus64,12,1); // in 64 bit slot
|
||||
ADD_FIELD32(pcix,13,1); // Pci mode
|
||||
ADD_FIELD32(pcixspd,14,2); // pci x speed
|
||||
};
|
||||
STATUS sts;
|
||||
|
||||
struct EECD : public Reg<uint32_t> { // 0x0010 EECD Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(sk,0,1); // clack input to the eeprom
|
||||
ADD_FIELD32(cs,1,1); // chip select to eeprom
|
||||
ADD_FIELD32(din,2,1); // data input to eeprom
|
||||
ADD_FIELD32(dout,3,1); // data output bit
|
||||
ADD_FIELD32(fwe,4,2); // flash write enable
|
||||
ADD_FIELD32(ee_req,6,1); // request eeprom access
|
||||
ADD_FIELD32(ee_gnt,7,1); // grant eeprom access
|
||||
ADD_FIELD32(ee_pres,8,1); // eeprom present
|
||||
ADD_FIELD32(ee_size,9,1); // eeprom size
|
||||
ADD_FIELD32(ee_sz1,10,1); // eeprom size
|
||||
ADD_FIELD32(rsvd,11,2); // reserved
|
||||
ADD_FIELD32(ee_type,13,1); // type of eeprom
|
||||
} ;
|
||||
EECD eecd;
|
||||
|
||||
struct EERD : public Reg<uint32_t> { // 0x0014 EERD Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(start,0,1); // start read
|
||||
ADD_FIELD32(done,1,1); // done read
|
||||
ADD_FIELD32(addr,2,14); // address
|
||||
ADD_FIELD32(data,16,16); // data
|
||||
};
|
||||
EERD eerd;
|
||||
|
||||
struct CTRL_EXT : public Reg<uint32_t> { // 0x0018 CTRL_EXT Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(gpi_en,0,4); // enable interrupts from gpio
|
||||
ADD_FIELD32(phyint,5,1); // reads the phy internal int status
|
||||
ADD_FIELD32(sdp2_data,6,1); // data from gpio sdp
|
||||
ADD_FIELD32(spd3_data,7,1); // data frmo gpio sdp
|
||||
ADD_FIELD32(spd2_iodir,10,1); // direction of sdp2
|
||||
ADD_FIELD32(spd3_iodir,11,1); // direction of sdp2
|
||||
ADD_FIELD32(asdchk,12,1); // initiate auto-speed-detection
|
||||
ADD_FIELD32(eerst,13,1); // reset the eeprom
|
||||
ADD_FIELD32(spd_byps,15,1); // bypass speed select
|
||||
ADD_FIELD32(ro_dis,17,1); // disable relaxed memory ordering
|
||||
ADD_FIELD32(vreg,21,1); // power down the voltage regulator
|
||||
ADD_FIELD32(link_mode,22,2); // interface to talk to the link
|
||||
ADD_FIELD32(iame, 27,1); // interrupt acknowledge auto-mask ??
|
||||
ADD_FIELD32(drv_loaded, 28,1);// driver is loaded and incharge of device
|
||||
ADD_FIELD32(timer_clr, 29,1); // clear interrupt timers after IMS clear ??
|
||||
};
|
||||
CTRL_EXT ctrl_ext;
|
||||
|
||||
struct MDIC : public Reg<uint32_t> { // 0x0020 MDIC Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(data,0,16); // data
|
||||
ADD_FIELD32(regadd,16,5); // register address
|
||||
ADD_FIELD32(phyadd,21,5); // phy addresses
|
||||
ADD_FIELD32(op,26,2); // opcode
|
||||
ADD_FIELD32(r,28,1); // ready
|
||||
ADD_FIELD32(i,29,1); // interrupt
|
||||
ADD_FIELD32(e,30,1); // error
|
||||
};
|
||||
MDIC mdic;
|
||||
|
||||
struct ICR : public Reg<uint32_t> { // 0x00C0 ICR Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(txdw,0,1) // tx descr witten back
|
||||
ADD_FIELD32(txqe,1,1) // tx queue empty
|
||||
ADD_FIELD32(lsc,2,1) // link status change
|
||||
ADD_FIELD32(rxseq,3,1) // rcv sequence error
|
||||
ADD_FIELD32(rxdmt0,4,1) // rcv descriptor min thresh
|
||||
ADD_FIELD32(rsvd1,5,1) // reserved
|
||||
ADD_FIELD32(rxo,6,1) // receive overrunn
|
||||
ADD_FIELD32(rxt0,7,1) // receiver timer interrupt
|
||||
ADD_FIELD32(mdac,9,1) // mdi/o access complete
|
||||
ADD_FIELD32(rxcfg,10,1) // recv /c/ ordered sets
|
||||
ADD_FIELD32(phyint,12,1) // phy interrupt
|
||||
ADD_FIELD32(gpi1,13,1) // gpi int 1
|
||||
ADD_FIELD32(gpi2,14,1) // gpi int 2
|
||||
ADD_FIELD32(txdlow,15,1) // transmit desc low thresh
|
||||
ADD_FIELD32(srpd,16,1) // small receive packet detected
|
||||
ADD_FIELD32(ack,17,1); // receive ack frame
|
||||
ADD_FIELD32(int_assert, 31,1); // interrupt caused a system interrupt
|
||||
};
|
||||
ICR icr;
|
||||
|
||||
uint32_t imr; // register that contains the current interrupt mask
|
||||
|
||||
struct ITR : public Reg<uint32_t> { // 0x00C4 ITR Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(interval, 0,16); // minimum inter-interrutp inteval
|
||||
// specified in 256ns interrupts
|
||||
};
|
||||
ITR itr;
|
||||
|
||||
// When CTRL_EXT.IAME and the ICR.INT_ASSERT is 1 an ICR read or write
|
||||
// causes the IAM register contents to be written into the IMC
|
||||
// automatically clearing all interrupts that have a bit in the IAM set
|
||||
uint32_t iam;
|
||||
|
||||
struct RCTL : public Reg<uint32_t> { // 0x0100 RCTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(rst,0,1); // Reset
|
||||
ADD_FIELD32(en,1,1); // Enable
|
||||
ADD_FIELD32(sbp,2,1); // Store bad packets
|
||||
ADD_FIELD32(upe,3,1); // Unicast Promiscuous enabled
|
||||
ADD_FIELD32(mpe,4,1); // Multicast promiscuous enabled
|
||||
ADD_FIELD32(lpe,5,1); // long packet reception enabled
|
||||
ADD_FIELD32(lbm,6,2); //
|
||||
ADD_FIELD32(rdmts,8,2); //
|
||||
ADD_FIELD32(mo,12,2); //
|
||||
ADD_FIELD32(mdr,14,1); //
|
||||
ADD_FIELD32(bam,15,1); //
|
||||
ADD_FIELD32(bsize,16,2); //
|
||||
ADD_FIELD32(vfe,18,1); //
|
||||
ADD_FIELD32(cfien,19,1); //
|
||||
ADD_FIELD32(cfi,20,1); //
|
||||
ADD_FIELD32(dpf,22,1); // discard pause frames
|
||||
ADD_FIELD32(pmcf,23,1); // pass mac control frames
|
||||
ADD_FIELD32(bsex,25,1); // buffer size extension
|
||||
ADD_FIELD32(secrc,26,1); // strip ethernet crc from incoming packet
|
||||
unsigned descSize()
|
||||
{
|
||||
switch(bsize()) {
|
||||
case 0: return bsex() == 0 ? 2048 : 0;
|
||||
case 1: return bsex() == 0 ? 1024 : 16384;
|
||||
case 2: return bsex() == 0 ? 512 : 8192;
|
||||
case 3: return bsex() == 0 ? 256 : 4096;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
RCTL rctl;
|
||||
|
||||
struct FCTTV : public Reg<uint32_t> { // 0x0170 FCTTV
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(ttv,0,16); // Transmit Timer Value
|
||||
};
|
||||
FCTTV fcttv;
|
||||
|
||||
struct TCTL : public Reg<uint32_t> { // 0x0400 TCTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(rst,0,1); // Reset
|
||||
ADD_FIELD32(en,1,1); // Enable
|
||||
ADD_FIELD32(bce,2,1); // busy check enable
|
||||
ADD_FIELD32(psp,3,1); // pad short packets
|
||||
ADD_FIELD32(ct,4,8); // collision threshold
|
||||
ADD_FIELD32(cold,12,10); // collision distance
|
||||
ADD_FIELD32(swxoff,22,1); // software xoff transmission
|
||||
ADD_FIELD32(pbe,23,1); // packet burst enable
|
||||
ADD_FIELD32(rtlc,24,1); // retransmit late collisions
|
||||
ADD_FIELD32(nrtu,25,1); // on underrun no TX
|
||||
ADD_FIELD32(mulr,26,1); // multiple request
|
||||
};
|
||||
TCTL tctl;
|
||||
|
||||
struct PBA : public Reg<uint32_t> { // 0x1000 PBA Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(rxa,0,16);
|
||||
ADD_FIELD32(txa,16,16);
|
||||
};
|
||||
PBA pba;
|
||||
|
||||
struct FCRTL : public Reg<uint32_t> { // 0x2160 FCRTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(rtl,3,28); // make this bigger than the spec so we can have
|
||||
// a larger buffer
|
||||
ADD_FIELD32(xone, 31,1);
|
||||
};
|
||||
FCRTL fcrtl;
|
||||
|
||||
struct FCRTH : public Reg<uint32_t> { // 0x2168 FCRTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(rth,3,13); // make this bigger than the spec so we can have
|
||||
//a larger buffer
|
||||
ADD_FIELD32(xfce, 31,1);
|
||||
};
|
||||
FCRTH fcrth;
|
||||
|
||||
struct RDBA : public Reg<uint64_t> { // 0x2800 RDBA Register
|
||||
using Reg<uint64_t>::operator=;
|
||||
ADD_FIELD64(rdbal,0,32); // base address of rx descriptor ring
|
||||
ADD_FIELD64(rdbah,32,32); // base address of rx descriptor ring
|
||||
};
|
||||
RDBA rdba;
|
||||
|
||||
struct RDLEN : public Reg<uint32_t> { // 0x2808 RDLEN Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(len,7,13); // number of bytes in the descriptor buffer
|
||||
};
|
||||
RDLEN rdlen;
|
||||
|
||||
struct SRRCTL : public Reg<uint32_t> { // 0x280C SRRCTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(pktlen, 0, 8);
|
||||
ADD_FIELD32(hdrlen, 8, 8); // guess based on header, not documented
|
||||
ADD_FIELD32(desctype, 25,3); // type of descriptor 000 legacy, 001 adv,
|
||||
//101 hdr split
|
||||
unsigned bufLen() { return pktlen() << 10; }
|
||||
unsigned hdrLen() { return hdrlen() << 6; }
|
||||
};
|
||||
SRRCTL srrctl;
|
||||
|
||||
struct RDH : public Reg<uint32_t> { // 0x2810 RDH Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(rdh,0,16); // head of the descriptor ring
|
||||
};
|
||||
RDH rdh;
|
||||
|
||||
struct RDT : public Reg<uint32_t> { // 0x2818 RDT Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(rdt,0,16); // tail of the descriptor ring
|
||||
};
|
||||
RDT rdt;
|
||||
|
||||
struct RDTR : public Reg<uint32_t> { // 0x2820 RDTR Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(delay,0,16); // receive delay timer
|
||||
ADD_FIELD32(fpd, 31,1); // flush partial descriptor block ??
|
||||
};
|
||||
RDTR rdtr;
|
||||
|
||||
struct RXDCTL : public Reg<uint32_t> { // 0x2828 RXDCTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(pthresh,0,6); // prefetch threshold, less that this
|
||||
// consider prefetch
|
||||
ADD_FIELD32(hthresh,8,6); // number of descriptors in host mem to
|
||||
// consider prefetch
|
||||
ADD_FIELD32(wthresh,16,6); // writeback threshold
|
||||
ADD_FIELD32(gran,24,1); // granularity 0 = desc, 1 = cacheline
|
||||
};
|
||||
RXDCTL rxdctl;
|
||||
|
||||
struct RADV : public Reg<uint32_t> { // 0x282C RADV Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(idv,0,16); // absolute interrupt delay
|
||||
};
|
||||
RADV radv;
|
||||
|
||||
struct RSRPD : public Reg<uint32_t> { // 0x2C00 RSRPD Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(idv,0,12); // size to interrutp on small packets
|
||||
};
|
||||
RSRPD rsrpd;
|
||||
|
||||
struct TDBA : public Reg<uint64_t> { // 0x3800 TDBAL Register
|
||||
using Reg<uint64_t>::operator=;
|
||||
ADD_FIELD64(tdbal,0,32); // base address of transmit descriptor ring
|
||||
ADD_FIELD64(tdbah,32,32); // base address of transmit descriptor ring
|
||||
};
|
||||
TDBA tdba;
|
||||
|
||||
struct TDLEN : public Reg<uint32_t> { // 0x3808 TDLEN Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(len,7,13); // number of bytes in the descriptor buffer
|
||||
};
|
||||
TDLEN tdlen;
|
||||
|
||||
struct TDH : public Reg<uint32_t> { // 0x3810 TDH Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(tdh,0,16); // head of the descriptor ring
|
||||
};
|
||||
TDH tdh;
|
||||
|
||||
struct TXDCA_CTL : public Reg<uint32_t> { // 0x3814 TXDCA_CTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(cpu_mask, 0, 5);
|
||||
ADD_FIELD32(enabled, 5,1);
|
||||
ADD_FIELD32(relax_ordering, 6, 1);
|
||||
};
|
||||
TXDCA_CTL txdca_ctl;
|
||||
|
||||
struct TDT : public Reg<uint32_t> { // 0x3818 TDT Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(tdt,0,16); // tail of the descriptor ring
|
||||
};
|
||||
TDT tdt;
|
||||
|
||||
struct TIDV : public Reg<uint32_t> { // 0x3820 TIDV Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(idv,0,16); // interrupt delay
|
||||
};
|
||||
TIDV tidv;
|
||||
|
||||
struct TXDCTL : public Reg<uint32_t> { // 0x3828 TXDCTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(pthresh, 0,6); // if number of descriptors control has is
|
||||
// below this number, a prefetch is considered
|
||||
ADD_FIELD32(hthresh,8,8); // number of valid descriptors is host memory
|
||||
// before a prefetch is considered
|
||||
ADD_FIELD32(wthresh,16,6); // number of descriptors to keep until
|
||||
// writeback is considered
|
||||
ADD_FIELD32(gran, 24,1); // granulatiry of above values (0 = cacheline,
|
||||
// 1 == desscriptor)
|
||||
ADD_FIELD32(lwthresh,25,7); // xmit descriptor low thresh, interrupt
|
||||
// below this level
|
||||
};
|
||||
TXDCTL txdctl;
|
||||
|
||||
struct TADV : public Reg<uint32_t> { // 0x382C TADV Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(idv,0,16); // absolute interrupt delay
|
||||
};
|
||||
TADV tadv;
|
||||
/*
|
||||
struct TDWBA : public Reg<uint64_t> { // 0x3838 TDWBA Register
|
||||
using Reg<uint64_t>::operator=;
|
||||
ADD_FIELD64(en,0,1); // enable transmit description ring address writeback
|
||||
ADD_FIELD64(tdwbal,2,32); // base address of transmit descriptor ring address writeback
|
||||
ADD_FIELD64(tdwbah,32,32); // base address of transmit descriptor ring
|
||||
};
|
||||
TDWBA tdwba;*/
|
||||
uint64_t tdwba;
|
||||
|
||||
struct RXCSUM : public Reg<uint32_t> { // 0x5000 RXCSUM Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(pcss,0,8);
|
||||
ADD_FIELD32(ipofld,8,1);
|
||||
ADD_FIELD32(tuofld,9,1);
|
||||
ADD_FIELD32(pcsd, 13,1);
|
||||
};
|
||||
RXCSUM rxcsum;
|
||||
|
||||
uint32_t rlpml; // 0x5004 RLPML probably maximum accepted packet size
|
||||
|
||||
struct RFCTL : public Reg<uint32_t> { // 0x5008 RFCTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(iscsi_dis,0,1);
|
||||
ADD_FIELD32(iscsi_dwc,1,5);
|
||||
ADD_FIELD32(nfsw_dis,6,1);
|
||||
ADD_FIELD32(nfsr_dis,7,1);
|
||||
ADD_FIELD32(nfs_ver,8,2);
|
||||
ADD_FIELD32(ipv6_dis,10,1);
|
||||
ADD_FIELD32(ipv6xsum_dis,11,1);
|
||||
ADD_FIELD32(ackdis,13,1);
|
||||
ADD_FIELD32(ipfrsp_dis,14,1);
|
||||
ADD_FIELD32(exsten,15,1);
|
||||
};
|
||||
RFCTL rfctl;
|
||||
|
||||
struct MANC : public Reg<uint32_t> { // 0x5820 MANC Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(smbus,0,1); // SMBus enabled #####
|
||||
ADD_FIELD32(asf,1,1); // ASF enabled #####
|
||||
ADD_FIELD32(ronforce,2,1); // reset of force
|
||||
ADD_FIELD32(rsvd,3,5); // reserved
|
||||
ADD_FIELD32(rmcp1,8,1); // rcmp1 filtering
|
||||
ADD_FIELD32(rmcp2,9,1); // rcmp2 filtering
|
||||
ADD_FIELD32(ipv4,10,1); // enable ipv4
|
||||
ADD_FIELD32(ipv6,11,1); // enable ipv6
|
||||
ADD_FIELD32(snap,12,1); // accept snap
|
||||
ADD_FIELD32(arp,13,1); // filter arp #####
|
||||
ADD_FIELD32(neighbor,14,1); // neighbor discovery
|
||||
ADD_FIELD32(arp_resp,15,1); // arp response
|
||||
ADD_FIELD32(tcorst,16,1); // tco reset happened
|
||||
ADD_FIELD32(rcvtco,17,1); // receive tco enabled ######
|
||||
ADD_FIELD32(blkphyrst,18,1);// block phy resets ########
|
||||
ADD_FIELD32(rcvall,19,1); // receive all
|
||||
ADD_FIELD32(macaddrfltr,20,1); // mac address filtering ######
|
||||
ADD_FIELD32(mng2host,21,1); // mng2 host packets #######
|
||||
ADD_FIELD32(ipaddrfltr,22,1); // ip address filtering
|
||||
ADD_FIELD32(xsumfilter,23,1); // checksum filtering
|
||||
ADD_FIELD32(brfilter,24,1); // broadcast filtering
|
||||
ADD_FIELD32(smbreq,25,1); // smb request
|
||||
ADD_FIELD32(smbgnt,26,1); // smb grant
|
||||
ADD_FIELD32(smbclkin,27,1); // smbclkin
|
||||
ADD_FIELD32(smbdatain,28,1); // smbdatain
|
||||
ADD_FIELD32(smbdataout,29,1); // smb data out
|
||||
ADD_FIELD32(smbclkout,30,1); // smb clock out
|
||||
};
|
||||
MANC manc;
|
||||
|
||||
struct SWSM : public Reg<uint32_t> { // 0x5B50 SWSM register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(smbi,0,1); // Semaphone bit
|
||||
ADD_FIELD32(swesmbi, 1,1); // Software eeporm semaphore
|
||||
ADD_FIELD32(wmng, 2,1); // Wake MNG clock
|
||||
ADD_FIELD32(reserved, 3, 29);
|
||||
};
|
||||
SWSM swsm;
|
||||
|
||||
struct FWSM : public Reg<uint32_t> { // 0x5B54 FWSM register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(eep_fw_semaphore,0,1);
|
||||
ADD_FIELD32(fw_mode, 1,3);
|
||||
ADD_FIELD32(ide, 4,1);
|
||||
ADD_FIELD32(sol, 5,1);
|
||||
ADD_FIELD32(eep_roload, 6,1);
|
||||
ADD_FIELD32(reserved, 7,8);
|
||||
ADD_FIELD32(fw_val_bit, 15, 1);
|
||||
ADD_FIELD32(reset_cnt, 16, 3);
|
||||
ADD_FIELD32(ext_err_ind, 19, 6);
|
||||
ADD_FIELD32(reserved2, 25, 7);
|
||||
};
|
||||
FWSM fwsm;
|
||||
|
||||
uint32_t sw_fw_sync;
|
||||
|
||||
void serialize(std::ostream &os)
|
||||
{
|
||||
paramOut(os, "ctrl", ctrl._data);
|
||||
paramOut(os, "sts", sts._data);
|
||||
paramOut(os, "eecd", eecd._data);
|
||||
paramOut(os, "eerd", eerd._data);
|
||||
paramOut(os, "ctrl_ext", ctrl_ext._data);
|
||||
paramOut(os, "mdic", mdic._data);
|
||||
paramOut(os, "icr", icr._data);
|
||||
SERIALIZE_SCALAR(imr);
|
||||
paramOut(os, "itr", itr._data);
|
||||
SERIALIZE_SCALAR(iam);
|
||||
paramOut(os, "rctl", rctl._data);
|
||||
paramOut(os, "fcttv", fcttv._data);
|
||||
paramOut(os, "tctl", tctl._data);
|
||||
paramOut(os, "pba", pba._data);
|
||||
paramOut(os, "fcrtl", fcrtl._data);
|
||||
paramOut(os, "fcrth", fcrth._data);
|
||||
paramOut(os, "rdba", rdba._data);
|
||||
paramOut(os, "rdlen", rdlen._data);
|
||||
paramOut(os, "srrctl", srrctl._data);
|
||||
paramOut(os, "rdh", rdh._data);
|
||||
paramOut(os, "rdt", rdt._data);
|
||||
paramOut(os, "rdtr", rdtr._data);
|
||||
paramOut(os, "rxdctl", rxdctl._data);
|
||||
paramOut(os, "radv", radv._data);
|
||||
paramOut(os, "rsrpd", rsrpd._data);
|
||||
paramOut(os, "tdba", tdba._data);
|
||||
paramOut(os, "tdlen", tdlen._data);
|
||||
paramOut(os, "tdh", tdh._data);
|
||||
paramOut(os, "txdca_ctl", txdca_ctl._data);
|
||||
paramOut(os, "tdt", tdt._data);
|
||||
paramOut(os, "tidv", tidv._data);
|
||||
paramOut(os, "txdctl", txdctl._data);
|
||||
paramOut(os, "tadv", tadv._data);
|
||||
//paramOut(os, "tdwba", tdwba._data);
|
||||
SERIALIZE_SCALAR(tdwba);
|
||||
paramOut(os, "rxcsum", rxcsum._data);
|
||||
SERIALIZE_SCALAR(rlpml);
|
||||
paramOut(os, "rfctl", rfctl._data);
|
||||
paramOut(os, "manc", manc._data);
|
||||
paramOut(os, "swsm", swsm._data);
|
||||
paramOut(os, "fwsm", fwsm._data);
|
||||
SERIALIZE_SCALAR(sw_fw_sync);
|
||||
}
|
||||
|
||||
void unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
paramIn(cp, section, "ctrl", ctrl._data);
|
||||
paramIn(cp, section, "sts", sts._data);
|
||||
paramIn(cp, section, "eecd", eecd._data);
|
||||
paramIn(cp, section, "eerd", eerd._data);
|
||||
paramIn(cp, section, "ctrl_ext", ctrl_ext._data);
|
||||
paramIn(cp, section, "mdic", mdic._data);
|
||||
paramIn(cp, section, "icr", icr._data);
|
||||
UNSERIALIZE_SCALAR(imr);
|
||||
paramIn(cp, section, "itr", itr._data);
|
||||
UNSERIALIZE_SCALAR(iam);
|
||||
paramIn(cp, section, "rctl", rctl._data);
|
||||
paramIn(cp, section, "fcttv", fcttv._data);
|
||||
paramIn(cp, section, "tctl", tctl._data);
|
||||
paramIn(cp, section, "pba", pba._data);
|
||||
paramIn(cp, section, "fcrtl", fcrtl._data);
|
||||
paramIn(cp, section, "fcrth", fcrth._data);
|
||||
paramIn(cp, section, "rdba", rdba._data);
|
||||
paramIn(cp, section, "rdlen", rdlen._data);
|
||||
paramIn(cp, section, "srrctl", srrctl._data);
|
||||
paramIn(cp, section, "rdh", rdh._data);
|
||||
paramIn(cp, section, "rdt", rdt._data);
|
||||
paramIn(cp, section, "rdtr", rdtr._data);
|
||||
paramIn(cp, section, "rxdctl", rxdctl._data);
|
||||
paramIn(cp, section, "radv", radv._data);
|
||||
paramIn(cp, section, "rsrpd", rsrpd._data);
|
||||
paramIn(cp, section, "tdba", tdba._data);
|
||||
paramIn(cp, section, "tdlen", tdlen._data);
|
||||
paramIn(cp, section, "tdh", tdh._data);
|
||||
paramIn(cp, section, "txdca_ctl", txdca_ctl._data);
|
||||
paramIn(cp, section, "tdt", tdt._data);
|
||||
paramIn(cp, section, "tidv", tidv._data);
|
||||
paramIn(cp, section, "txdctl", txdctl._data);
|
||||
paramIn(cp, section, "tadv", tadv._data);
|
||||
UNSERIALIZE_SCALAR(tdwba);
|
||||
//paramIn(cp, section, "tdwba", tdwba._data);
|
||||
paramIn(cp, section, "rxcsum", rxcsum._data);
|
||||
UNSERIALIZE_SCALAR(rlpml);
|
||||
paramIn(cp, section, "rfctl", rfctl._data);
|
||||
paramIn(cp, section, "manc", manc._data);
|
||||
paramIn(cp, section, "swsm", swsm._data);
|
||||
paramIn(cp, section, "fwsm", fwsm._data);
|
||||
UNSERIALIZE_SCALAR(sw_fw_sync);
|
||||
}
|
||||
};
|
||||
} // namespace iGbReg
|
||||
290
simulators/gem5/src/dev/ide_atareg.h
Normal file
290
simulators/gem5/src/dev/ide_atareg.h
Normal file
@ -0,0 +1,290 @@
|
||||
/* $OpenBSD: atareg.h,v 1.12 2004/09/24 07:15:22 grange Exp $ */
|
||||
/* $NetBSD: atareg.h,v 1.5 1999/01/18 20:06:24 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Manuel Bouyer.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_ATA_ATAREG_H_
|
||||
#define _DEV_ATA_ATAREG_H_
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <endian.h>
|
||||
#elif defined(__sun)
|
||||
#include <sys/isa_defs.h>
|
||||
#else
|
||||
#include <machine/endian.h>
|
||||
#endif
|
||||
|
||||
#ifdef LITTLE_ENDIAN
|
||||
#define ATA_BYTE_ORDER LITTLE_ENDIAN
|
||||
#elif defined(BIG_ENDIAN)
|
||||
#define ATA_BYTE_ORDER BIG_ENDIAN
|
||||
#elif defined(_LITTLE_ENDIAN)
|
||||
#define ATA_BYTE_ORDER 1
|
||||
#define LITTLE_ENDIAN 1
|
||||
#elif defined(_BIG_ENDIAN)
|
||||
#define ATA_BYTE_ORDER 0
|
||||
#define LITTLE_ENDIAN 1
|
||||
#else
|
||||
#error "No endianess defined"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Drive parameter structure for ATA/ATAPI.
|
||||
* Bit fields: WDC_* : common to ATA/ATAPI
|
||||
* ATA_* : ATA only
|
||||
* ATAPI_* : ATAPI only.
|
||||
*/
|
||||
struct ataparams {
|
||||
/* drive info */
|
||||
uint16_t atap_config; /* 0: general configuration */
|
||||
#define WDC_CFG_ATAPI_MASK 0xc000
|
||||
#define WDC_CFG_ATAPI 0x8000
|
||||
#define ATA_CFG_REMOVABLE 0x0080
|
||||
#define ATA_CFG_FIXED 0x0040
|
||||
#define ATAPI_CFG_TYPE_MASK 0x1f00
|
||||
#define ATAPI_CFG_TYPE(x) (((x) & ATAPI_CFG_TYPE_MASK) >> 8)
|
||||
#define ATAPI_CFG_TYPE_DIRECT 0x00
|
||||
#define ATAPI_CFG_TYPE_SEQUENTIAL 0x01
|
||||
#define ATAPI_CFG_TYPE_CDROM 0x05
|
||||
#define ATAPI_CFG_TYPE_OPTICAL 0x07
|
||||
#define ATAPI_CFG_TYPE_NODEVICE 0x1F
|
||||
#define ATAPI_CFG_REMOV 0x0080
|
||||
#define ATAPI_CFG_DRQ_MASK 0x0060
|
||||
#define ATAPI_CFG_STD_DRQ 0x0000
|
||||
#define ATAPI_CFG_IRQ_DRQ 0x0020
|
||||
#define ATAPI_CFG_ACCEL_DRQ 0x0040
|
||||
#define ATAPI_CFG_CMD_MASK 0x0003
|
||||
#define ATAPI_CFG_CMD_12 0x0000
|
||||
#define ATAPI_CFG_CMD_16 0x0001
|
||||
/* words 1-9 are ATA only */
|
||||
uint16_t atap_cylinders; /* 1: # of non-removable cylinders */
|
||||
uint16_t __reserved1;
|
||||
uint16_t atap_heads; /* 3: # of heads */
|
||||
uint16_t __retired1[2]; /* 4-5: # of unform. bytes/track */
|
||||
uint16_t atap_sectors; /* 6: # of sectors */
|
||||
uint16_t __retired2[3];
|
||||
|
||||
uint8_t atap_serial[20]; /* 10-19: serial number */
|
||||
uint16_t __retired3[2];
|
||||
uint16_t __obsolete1;
|
||||
uint8_t atap_revision[8]; /* 23-26: firmware revision */
|
||||
uint8_t atap_model[40]; /* 27-46: model number */
|
||||
uint16_t atap_multi; /* 47: maximum sectors per irq (ATA) */
|
||||
uint16_t __reserved2;
|
||||
uint8_t atap_vendor; /* 49: vendor */
|
||||
uint8_t atap_capabilities1; /* 49: capability flags */
|
||||
#define WDC_CAP_IORDY 0x0800
|
||||
#define WDC_CAP_IORDY_DSBL 0x0400
|
||||
#define WDC_CAP_LBA 0x0200
|
||||
#define WDC_CAP_DMA 0x0100
|
||||
#define ATA_CAP_STBY 0x2000
|
||||
#define ATAPI_CAP_INTERL_DMA 0x8000
|
||||
#define ATAPI_CAP_CMD_QUEUE 0x4000
|
||||
#define ATAPI_CAP_OVERLP 0x2000
|
||||
#define ATAPI_CAP_ATA_RST 0x1000
|
||||
uint16_t atap_capabilities2; /* 50: capability flags (ATA) */
|
||||
#if ATA_BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint8_t __junk2;
|
||||
uint8_t atap_oldpiotiming; /* 51: old PIO timing mode */
|
||||
uint8_t __junk3;
|
||||
uint8_t atap_olddmatiming; /* 52: old DMA timing mode (ATA) */
|
||||
#else
|
||||
uint8_t atap_oldpiotiming; /* 51: old PIO timing mode */
|
||||
uint8_t __junk2;
|
||||
uint8_t atap_olddmatiming; /* 52: old DMA timing mode (ATA) */
|
||||
uint8_t __junk3;
|
||||
#endif
|
||||
uint16_t atap_extensions; /* 53: extensions supported */
|
||||
#define WDC_EXT_UDMA_MODES 0x0004
|
||||
#define WDC_EXT_MODES 0x0002
|
||||
#define WDC_EXT_GEOM 0x0001
|
||||
/* words 54-62 are ATA only */
|
||||
uint16_t atap_curcylinders; /* 54: current logical cylinders */
|
||||
uint16_t atap_curheads; /* 55: current logical heads */
|
||||
uint16_t atap_cursectors; /* 56: current logical sectors/tracks */
|
||||
uint16_t atap_curcapacity[2]; /* 57-58: current capacity */
|
||||
uint8_t atap_curmulti; /* 59: current multi-sector setting */
|
||||
uint8_t atap_curmulti_valid; /* 59: current multi-sector setting */
|
||||
#define WDC_MULTI_VALID 0x0100
|
||||
#define WDC_MULTI_MASK 0x00ff
|
||||
uint32_t atap_capacity; /* 60-61: total capacity (LBA only) */
|
||||
uint16_t __retired4;
|
||||
#if ATA_BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint8_t atap_dmamode_supp; /* 63: multiword DMA mode supported */
|
||||
uint8_t atap_dmamode_act; /* multiword DMA mode active */
|
||||
uint8_t atap_piomode_supp; /* 64: PIO mode supported */
|
||||
uint8_t __junk4;
|
||||
#else
|
||||
uint8_t atap_dmamode_act; /* multiword DMA mode active */
|
||||
uint8_t atap_dmamode_supp; /* 63: multiword DMA mode supported */
|
||||
uint8_t __junk4;
|
||||
uint8_t atap_piomode_supp; /* 64: PIO mode supported */
|
||||
#endif
|
||||
uint16_t atap_dmatiming_mimi; /* 65: minimum DMA cycle time */
|
||||
uint16_t atap_dmatiming_recom; /* 66: recommended DMA cycle time */
|
||||
uint16_t atap_piotiming; /* 67: mini PIO cycle time without FC */
|
||||
uint16_t atap_piotiming_iordy; /* 68: mini PIO cycle time with IORDY FC */
|
||||
uint16_t __reserved3[2];
|
||||
/* words 71-72 are ATAPI only */
|
||||
uint16_t atap_pkt_br; /* 71: time (ns) to bus release */
|
||||
uint16_t atap_pkt_bsyclr; /* 72: tme to clear BSY after service */
|
||||
uint16_t __reserved4[2];
|
||||
uint16_t atap_queuedepth; /* 75: */
|
||||
#define WDC_QUEUE_DEPTH_MASK 0x1f
|
||||
uint16_t atap_sata_caps; /* 76: SATA capabilities */
|
||||
#define SATA_SIGNAL_GEN1 0x0002 /* SATA Gen-1 signaling speed */
|
||||
#define SATA_SIGNAL_GEN2 0x0004 /* SATA Gen-2 signaling speed */
|
||||
#define SATA_NATIVE_CMDQ 0x0100 /* native command queuing */
|
||||
#define SATA_HOST_PWR_MGMT 0x0200 /* power management (host) */
|
||||
uint16_t atap_sata_reserved; /* 77: reserved */
|
||||
uint16_t atap_sata_features_supp;/* 78: SATA features supported */
|
||||
#define SATA_NONZERO_OFFSETS 0x0002 /* non-zero buffer offsets */
|
||||
#define SATA_DMA_SETUP_AUTO 0x0004 /* DMA setup auto-activate */
|
||||
#define SATA_DRIVE_PWR_MGMT 0x0008 /* power management (device) */
|
||||
uint16_t atap_sata_features_en; /* 79: SATA features enabled */
|
||||
uint16_t atap_ata_major; /* 80: Major version number */
|
||||
#define WDC_VER_ATA1 0x0002
|
||||
#define WDC_VER_ATA2 0x0004
|
||||
#define WDC_VER_ATA3 0x0008
|
||||
#define WDC_VER_ATA4 0x0010
|
||||
#define WDC_VER_ATA5 0x0020
|
||||
#define WDC_VER_ATA6 0x0040
|
||||
#define WDC_VER_ATA7 0x0080
|
||||
#define WDC_VER_ATA8 0x0100
|
||||
#define WDC_VER_ATA9 0x0200
|
||||
#define WDC_VER_ATA10 0x0400
|
||||
#define WDC_VER_ATA11 0x0800
|
||||
#define WDC_VER_ATA12 0x1000
|
||||
#define WDC_VER_ATA13 0x2000
|
||||
#define WDC_VER_ATA14 0x4000
|
||||
uint16_t atap_ata_minor; /* 81: Minor version number */
|
||||
uint16_t atap_cmd_set1; /* 82: command set supported */
|
||||
#define WDC_CMD1_NOP 0x4000
|
||||
#define WDC_CMD1_RB 0x2000
|
||||
#define WDC_CMD1_WB 0x1000
|
||||
#define WDC_CMD1_HPA 0x0400
|
||||
#define WDC_CMD1_DVRST 0x0200
|
||||
#define WDC_CMD1_SRV 0x0100
|
||||
#define WDC_CMD1_RLSE 0x0080
|
||||
#define WDC_CMD1_AHEAD 0x0040
|
||||
#define WDC_CMD1_CACHE 0x0020
|
||||
#define WDC_CMD1_PKT 0x0010
|
||||
#define WDC_CMD1_PM 0x0008
|
||||
#define WDC_CMD1_REMOV 0x0004
|
||||
#define WDC_CMD1_SEC 0x0002
|
||||
#define WDC_CMD1_SMART 0x0001
|
||||
uint16_t atap_cmd_set2; /* 83: command set supported */
|
||||
#define ATAPI_CMD2_FCE 0x2000 /* Flush Cache Ext supported */
|
||||
#define ATAPI_CMD2_FC 0x1000 /* Flush Cache supported */
|
||||
#define ATAPI_CMD2_DCO 0x0800 /* Device Configuration Overlay supported */
|
||||
#define ATAPI_CMD2_48AD 0x0400 /* 48bit address supported */
|
||||
#define ATAPI_CMD2_AAM 0x0200 /* Automatic Acoustic Management supported */
|
||||
#define ATAPI_CMD2_SM 0x0100 /* Set Max security extension supported */
|
||||
#define ATAPI_CMD2_SF 0x0040 /* Set Features subcommand required */
|
||||
#define ATAPI_CMD2_PUIS 0x0020 /* Power up in standby supported */
|
||||
#define WDC_CMD2_RMSN 0x0010
|
||||
#define ATA_CMD2_APM 0x0008
|
||||
#define ATA_CMD2_CFA 0x0004
|
||||
#define ATA_CMD2_RWQ 0x0002
|
||||
#define WDC_CMD2_DM 0x0001 /* Download Microcode supported */
|
||||
uint16_t atap_cmd_ext; /* 84: command/features supp. ext. */
|
||||
#define ATAPI_CMDE_MSER 0x0004 /* Media serial number supported */
|
||||
#define ATAPI_CMDE_TEST 0x0002 /* SMART self-test supported */
|
||||
#define ATAPI_CMDE_SLOG 0x0001 /* SMART error logging supported */
|
||||
uint16_t atap_cmd1_en; /* 85: cmd/features enabled */
|
||||
/* bits are the same as atap_cmd_set1 */
|
||||
uint16_t atap_cmd2_en; /* 86: cmd/features enabled */
|
||||
/* bits are the same as atap_cmd_set2 */
|
||||
uint16_t atap_cmd_def; /* 87: cmd/features default */
|
||||
/* bits are NOT the same as atap_cmd_ext */
|
||||
#if ATA_BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint8_t atap_udmamode_supp; /* 88: Ultra-DMA mode supported */
|
||||
uint8_t atap_udmamode_act; /* Ultra-DMA mode active */
|
||||
#else
|
||||
uint8_t atap_udmamode_act; /* Ultra-DMA mode active */
|
||||
uint8_t atap_udmamode_supp; /* 88: Ultra-DMA mode supported */
|
||||
#endif
|
||||
/* 89-92 are ATA-only */
|
||||
uint16_t atap_seu_time; /* 89: Sec. Erase Unit compl. time */
|
||||
uint16_t atap_eseu_time; /* 90: Enhanced SEU compl. time */
|
||||
uint16_t atap_apm_val; /* 91: current APM value */
|
||||
uint16_t atap_mpasswd_rev; /* 92: Master Password revision */
|
||||
uint16_t atap_hwreset_res; /* 93: Hardware reset value */
|
||||
#define ATA_HWRES_CBLID 0x2000 /* CBLID above Vih */
|
||||
#define ATA_HWRES_D1_PDIAG 0x0800 /* Device 1 PDIAG detect OK */
|
||||
#define ATA_HWRES_D1_CSEL 0x0400 /* Device 1 used CSEL for address */
|
||||
#define ATA_HWRES_D1_JUMP 0x0200 /* Device 1 jumpered to address */
|
||||
#define ATA_HWRES_D0_SEL 0x0040 /* Device 0 responds when Dev 1 selected */
|
||||
#define ATA_HWRES_D0_DASP 0x0020 /* Device 0 DASP detect OK */
|
||||
#define ATA_HWRES_D0_PDIAG 0x0010 /* Device 0 PDIAG detect OK */
|
||||
#define ATA_HWRES_D0_DIAG 0x0008 /* Device 0 diag OK */
|
||||
#define ATA_HWRES_D0_CSEL 0x0004 /* Device 0 used CSEL for address */
|
||||
#define ATA_HWRES_D0_JUMP 0x0002 /* Device 0 jumpered to address */
|
||||
#if ATA_BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint8_t atap_acoustic_val; /* 94: Current acoustic level */
|
||||
uint8_t atap_acoustic_def; /* recommended level */
|
||||
#else
|
||||
uint8_t atap_acoustic_def; /* recommended level */
|
||||
uint8_t atap_acoustic_val; /* 94: Current acoustic level */
|
||||
#endif
|
||||
uint16_t __reserved6[5]; /* 95-99: reserved */
|
||||
uint16_t atap_max_lba[4]; /* 100-103: Max. user LBA add */
|
||||
uint16_t __reserved7[23]; /* 104-126: reserved */
|
||||
uint16_t atap_rmsn_supp; /* 127: remov. media status notif. */
|
||||
#define WDC_RMSN_SUPP_MASK 0x0003
|
||||
#define WDC_RMSN_SUPP 0x0001
|
||||
uint16_t atap_sec_st; /* 128: security status */
|
||||
#define WDC_SEC_LEV_MAX 0x0100
|
||||
#define WDC_SEC_ESE_SUPP 0x0020
|
||||
#define WDC_SEC_EXP 0x0010
|
||||
#define WDC_SEC_FROZEN 0x0008
|
||||
#define WDC_SEC_LOCKED 0x0004
|
||||
#define WDC_SEC_EN 0x0002
|
||||
#define WDC_SEC_SUPP 0x0001
|
||||
uint16_t __reserved8[31]; /* 129-159: vendor specific */
|
||||
uint16_t atap_cfa_power; /* 160: CFA powermode */
|
||||
#define ATAPI_CFA_MAX_MASK 0x0FFF
|
||||
#define ATAPI_CFA_MODE1_DIS 0x1000 /* CFA Mode 1 Disabled */
|
||||
#define ATAPI_CFA_MODE1_REQ 0x2000 /* CFA Mode 1 Required */
|
||||
#define ATAPI_CFA_WORD160 0x8000 /* Word 160 supported */
|
||||
uint16_t __reserved9[15]; /* 161-175: reserved for CFA */
|
||||
uint8_t atap_media_serial[60]; /* 176-205: media serial number */
|
||||
uint16_t __reserved10[49]; /* 206-254: reserved */
|
||||
#if ATA_BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint8_t atap_signature; /* 255: Signature */
|
||||
uint8_t atap_checksum; /* Checksum */
|
||||
#else
|
||||
uint8_t atap_checksum; /* Checksum */
|
||||
uint8_t atap_signature; /* 255: Signature */
|
||||
#endif
|
||||
};
|
||||
|
||||
#undef ATA_BYTE_ORDER
|
||||
#endif /* !_DEV_ATA_ATAREG_H_ */
|
||||
615
simulators/gem5/src/dev/ide_ctrl.cc
Normal file
615
simulators/gem5/src/dev/ide_ctrl.cc
Normal file
@ -0,0 +1,615 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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: Andrew Schultz
|
||||
* Ali Saidi
|
||||
* Miguel Serrano
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "cpu/intr_control.hh"
|
||||
#include "debug/IdeCtrl.hh"
|
||||
#include "dev/ide_ctrl.hh"
|
||||
#include "dev/ide_disk.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "params/IdeController.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
|
||||
// clang complains about std::set being overloaded with Packet::set if
|
||||
// we open up the entire namespace std
|
||||
using std::string;
|
||||
|
||||
// Bus master IDE registers
|
||||
enum BMIRegOffset {
|
||||
BMICommand = 0x0,
|
||||
BMIStatus = 0x2,
|
||||
BMIDescTablePtr = 0x4
|
||||
};
|
||||
|
||||
// PCI config space registers
|
||||
enum ConfRegOffset {
|
||||
PrimaryTiming = 0x40,
|
||||
SecondaryTiming = 0x42,
|
||||
DeviceTiming = 0x44,
|
||||
UDMAControl = 0x48,
|
||||
UDMATiming = 0x4A,
|
||||
IDEConfig = 0x54
|
||||
};
|
||||
|
||||
static const uint16_t timeRegWithDecodeEn = 0x8000;
|
||||
|
||||
IdeController::Channel::Channel(
|
||||
string newName, Addr _cmdSize, Addr _ctrlSize) :
|
||||
_name(newName),
|
||||
cmdAddr(0), cmdSize(_cmdSize), ctrlAddr(0), ctrlSize(_ctrlSize),
|
||||
master(NULL), slave(NULL), selected(NULL)
|
||||
{
|
||||
memset(&bmiRegs, 0, sizeof(bmiRegs));
|
||||
bmiRegs.status.dmaCap0 = 1;
|
||||
bmiRegs.status.dmaCap1 = 1;
|
||||
}
|
||||
|
||||
IdeController::Channel::~Channel()
|
||||
{
|
||||
}
|
||||
|
||||
IdeController::IdeController(Params *p)
|
||||
: PciDev(p), primary(name() + ".primary", BARSize[0], BARSize[1]),
|
||||
secondary(name() + ".secondary", BARSize[2], BARSize[3]),
|
||||
bmiAddr(0), bmiSize(BARSize[4]),
|
||||
primaryTiming(htole(timeRegWithDecodeEn)),
|
||||
secondaryTiming(htole(timeRegWithDecodeEn)),
|
||||
deviceTiming(0), udmaControl(0), udmaTiming(0), ideConfig(0),
|
||||
ioEnabled(false), bmEnabled(false),
|
||||
ioShift(p->io_shift), ctrlOffset(p->ctrl_offset)
|
||||
{
|
||||
if (params()->disks.size() > 3)
|
||||
panic("IDE controllers support a maximum of 4 devices attached!\n");
|
||||
|
||||
// Assign the disks to channels
|
||||
int numDisks = params()->disks.size();
|
||||
if (numDisks > 0)
|
||||
primary.master = params()->disks[0];
|
||||
if (numDisks > 1)
|
||||
primary.slave = params()->disks[1];
|
||||
if (numDisks > 2)
|
||||
secondary.master = params()->disks[2];
|
||||
if (numDisks > 3)
|
||||
secondary.slave = params()->disks[3];
|
||||
|
||||
for (int i = 0; i < params()->disks.size(); i++) {
|
||||
params()->disks[i]->setController(this);
|
||||
}
|
||||
primary.select(false);
|
||||
secondary.select(false);
|
||||
|
||||
if ((BARAddrs[0] & ~BAR_IO_MASK) && (!legacyIO[0] || ioShift)) {
|
||||
primary.cmdAddr = BARAddrs[0]; primary.cmdSize = BARSize[0];
|
||||
primary.ctrlAddr = BARAddrs[1]; primary.ctrlSize = BARAddrs[1];
|
||||
}
|
||||
if ((BARAddrs[2] & ~BAR_IO_MASK) && (!legacyIO[2] || ioShift)) {
|
||||
secondary.cmdAddr = BARAddrs[2]; secondary.cmdSize = BARSize[2];
|
||||
secondary.ctrlAddr = BARAddrs[3]; secondary.ctrlSize = BARAddrs[3];
|
||||
}
|
||||
|
||||
ioEnabled = (config.command & htole(PCI_CMD_IOSE));
|
||||
bmEnabled = (config.command & htole(PCI_CMD_BME));
|
||||
}
|
||||
|
||||
bool
|
||||
IdeController::isDiskSelected(IdeDisk *diskPtr)
|
||||
{
|
||||
return (primary.selected == diskPtr || secondary.selected == diskPtr);
|
||||
}
|
||||
|
||||
void
|
||||
IdeController::intrPost()
|
||||
{
|
||||
primary.bmiRegs.status.intStatus = 1;
|
||||
PciDev::intrPost();
|
||||
}
|
||||
|
||||
void
|
||||
IdeController::setDmaComplete(IdeDisk *disk)
|
||||
{
|
||||
Channel *channel;
|
||||
if (disk == primary.master || disk == primary.slave) {
|
||||
channel = &primary;
|
||||
} else if (disk == secondary.master || disk == secondary.slave) {
|
||||
channel = &secondary;
|
||||
} else {
|
||||
panic("Unable to find disk based on pointer %#x\n", disk);
|
||||
}
|
||||
|
||||
channel->bmiRegs.command.startStop = 0;
|
||||
channel->bmiRegs.status.active = 0;
|
||||
channel->bmiRegs.status.intStatus = 1;
|
||||
}
|
||||
|
||||
Tick
|
||||
IdeController::readConfig(PacketPtr pkt)
|
||||
{
|
||||
int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
|
||||
if (offset < PCI_DEVICE_SPECIFIC) {
|
||||
return PciDev::readConfig(pkt);
|
||||
}
|
||||
|
||||
pkt->allocate();
|
||||
|
||||
switch (pkt->getSize()) {
|
||||
case sizeof(uint8_t):
|
||||
switch (offset) {
|
||||
case DeviceTiming:
|
||||
pkt->set<uint8_t>(deviceTiming);
|
||||
break;
|
||||
case UDMAControl:
|
||||
pkt->set<uint8_t>(udmaControl);
|
||||
break;
|
||||
case PrimaryTiming + 1:
|
||||
pkt->set<uint8_t>(bits(htole(primaryTiming), 15, 8));
|
||||
break;
|
||||
case SecondaryTiming + 1:
|
||||
pkt->set<uint8_t>(bits(htole(secondaryTiming), 15, 8));
|
||||
break;
|
||||
case IDEConfig:
|
||||
pkt->set<uint8_t>(bits(htole(ideConfig), 7, 0));
|
||||
break;
|
||||
case IDEConfig + 1:
|
||||
pkt->set<uint8_t>(bits(htole(ideConfig), 15, 8));
|
||||
break;
|
||||
default:
|
||||
panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
|
||||
offset);
|
||||
}
|
||||
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset,
|
||||
(uint32_t)pkt->get<uint8_t>());
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
switch (offset) {
|
||||
case PrimaryTiming:
|
||||
pkt->set<uint16_t>(primaryTiming);
|
||||
break;
|
||||
case SecondaryTiming:
|
||||
pkt->set<uint16_t>(secondaryTiming);
|
||||
break;
|
||||
case UDMATiming:
|
||||
pkt->set<uint16_t>(udmaTiming);
|
||||
break;
|
||||
case IDEConfig:
|
||||
pkt->set<uint16_t>(ideConfig);
|
||||
break;
|
||||
default:
|
||||
panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
|
||||
offset);
|
||||
}
|
||||
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset,
|
||||
(uint32_t)pkt->get<uint16_t>());
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
if (offset == IDEConfig)
|
||||
pkt->set<uint32_t>(ideConfig);
|
||||
else
|
||||
panic("No 32bit reads implemented for this device.");
|
||||
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset,
|
||||
(uint32_t)pkt->get<uint32_t>());
|
||||
break;
|
||||
default:
|
||||
panic("invalid access size(?) for PCI configspace!\n");
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
return configDelay;
|
||||
}
|
||||
|
||||
|
||||
Tick
|
||||
IdeController::writeConfig(PacketPtr pkt)
|
||||
{
|
||||
int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
|
||||
if (offset < PCI_DEVICE_SPECIFIC) {
|
||||
PciDev::writeConfig(pkt);
|
||||
} else {
|
||||
switch (pkt->getSize()) {
|
||||
case sizeof(uint8_t):
|
||||
switch (offset) {
|
||||
case DeviceTiming:
|
||||
deviceTiming = pkt->get<uint8_t>();
|
||||
break;
|
||||
case UDMAControl:
|
||||
udmaControl = pkt->get<uint8_t>();
|
||||
break;
|
||||
case IDEConfig:
|
||||
replaceBits(ideConfig, 7, 0, pkt->get<uint8_t>());
|
||||
break;
|
||||
case IDEConfig + 1:
|
||||
replaceBits(ideConfig, 15, 8, pkt->get<uint8_t>());
|
||||
break;
|
||||
default:
|
||||
panic("Invalid PCI configuration write "
|
||||
"for size 1 offset: %#x!\n", offset);
|
||||
}
|
||||
DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
|
||||
offset, (uint32_t)pkt->get<uint8_t>());
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
switch (offset) {
|
||||
case PrimaryTiming:
|
||||
primaryTiming = pkt->get<uint16_t>();
|
||||
break;
|
||||
case SecondaryTiming:
|
||||
secondaryTiming = pkt->get<uint16_t>();
|
||||
break;
|
||||
case UDMATiming:
|
||||
udmaTiming = pkt->get<uint16_t>();
|
||||
break;
|
||||
case IDEConfig:
|
||||
ideConfig = pkt->get<uint16_t>();
|
||||
break;
|
||||
default:
|
||||
panic("Invalid PCI configuration write "
|
||||
"for size 2 offset: %#x!\n",
|
||||
offset);
|
||||
}
|
||||
DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n",
|
||||
offset, (uint32_t)pkt->get<uint16_t>());
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
if (offset == IDEConfig)
|
||||
ideConfig = pkt->get<uint32_t>();
|
||||
else
|
||||
panic("Write of unimplemented PCI config. register: %x\n", offset);
|
||||
break;
|
||||
default:
|
||||
panic("invalid access size(?) for PCI configspace!\n");
|
||||
}
|
||||
pkt->makeAtomicResponse();
|
||||
}
|
||||
|
||||
/* Trap command register writes and enable IO/BM as appropriate as well as
|
||||
* BARs. */
|
||||
switch(offset) {
|
||||
case PCI0_BASE_ADDR0:
|
||||
if (BARAddrs[0] != 0)
|
||||
primary.cmdAddr = BARAddrs[0];
|
||||
break;
|
||||
|
||||
case PCI0_BASE_ADDR1:
|
||||
if (BARAddrs[1] != 0)
|
||||
primary.ctrlAddr = BARAddrs[1];
|
||||
break;
|
||||
|
||||
case PCI0_BASE_ADDR2:
|
||||
if (BARAddrs[2] != 0)
|
||||
secondary.cmdAddr = BARAddrs[2];
|
||||
break;
|
||||
|
||||
case PCI0_BASE_ADDR3:
|
||||
if (BARAddrs[3] != 0)
|
||||
secondary.ctrlAddr = BARAddrs[3];
|
||||
break;
|
||||
|
||||
case PCI0_BASE_ADDR4:
|
||||
if (BARAddrs[4] != 0)
|
||||
bmiAddr = BARAddrs[4];
|
||||
break;
|
||||
|
||||
case PCI_COMMAND:
|
||||
DPRINTF(IdeCtrl, "Writing to PCI Command val: %#x\n", config.command);
|
||||
ioEnabled = (config.command & htole(PCI_CMD_IOSE));
|
||||
bmEnabled = (config.command & htole(PCI_CMD_BME));
|
||||
break;
|
||||
}
|
||||
return configDelay;
|
||||
}
|
||||
|
||||
void
|
||||
IdeController::Channel::accessCommand(Addr offset,
|
||||
int size, uint8_t *data, bool read)
|
||||
{
|
||||
const Addr SelectOffset = 6;
|
||||
const uint8_t SelectDevBit = 0x10;
|
||||
|
||||
if (!read && offset == SelectOffset)
|
||||
select(*data & SelectDevBit);
|
||||
|
||||
if (selected == NULL) {
|
||||
assert(size == sizeof(uint8_t));
|
||||
*data = 0;
|
||||
} else if (read) {
|
||||
selected->readCommand(offset, size, data);
|
||||
} else {
|
||||
selected->writeCommand(offset, size, data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IdeController::Channel::accessControl(Addr offset,
|
||||
int size, uint8_t *data, bool read)
|
||||
{
|
||||
if (selected == NULL) {
|
||||
assert(size == sizeof(uint8_t));
|
||||
*data = 0;
|
||||
} else if (read) {
|
||||
selected->readControl(offset, size, data);
|
||||
} else {
|
||||
selected->writeControl(offset, size, data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IdeController::Channel::accessBMI(Addr offset,
|
||||
int size, uint8_t *data, bool read)
|
||||
{
|
||||
assert(offset + size <= sizeof(BMIRegs));
|
||||
if (read) {
|
||||
memcpy(data, (uint8_t *)&bmiRegs + offset, size);
|
||||
} else {
|
||||
switch (offset) {
|
||||
case BMICommand:
|
||||
{
|
||||
if (size != sizeof(uint8_t))
|
||||
panic("Invalid BMIC write size: %x\n", size);
|
||||
|
||||
BMICommandReg oldVal = bmiRegs.command;
|
||||
BMICommandReg newVal = *data;
|
||||
|
||||
// if a DMA transfer is in progress, R/W control cannot change
|
||||
if (oldVal.startStop && oldVal.rw != newVal.rw)
|
||||
oldVal.rw = newVal.rw;
|
||||
|
||||
if (oldVal.startStop != newVal.startStop) {
|
||||
if (selected == NULL)
|
||||
panic("DMA start for disk which does not exist\n");
|
||||
|
||||
if (oldVal.startStop) {
|
||||
DPRINTF(IdeCtrl, "Stopping DMA transfer\n");
|
||||
bmiRegs.status.active = 0;
|
||||
|
||||
selected->abortDma();
|
||||
} else {
|
||||
DPRINTF(IdeCtrl, "Starting DMA transfer\n");
|
||||
bmiRegs.status.active = 1;
|
||||
|
||||
selected->startDma(letoh(bmiRegs.bmidtp));
|
||||
}
|
||||
}
|
||||
|
||||
bmiRegs.command = newVal;
|
||||
}
|
||||
break;
|
||||
case BMIStatus:
|
||||
{
|
||||
if (size != sizeof(uint8_t))
|
||||
panic("Invalid BMIS write size: %x\n", size);
|
||||
|
||||
BMIStatusReg oldVal = bmiRegs.status;
|
||||
BMIStatusReg newVal = *data;
|
||||
|
||||
// the BMIDEA bit is read only
|
||||
newVal.active = oldVal.active;
|
||||
|
||||
// to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
|
||||
if (oldVal.intStatus && newVal.intStatus)
|
||||
newVal.intStatus = 0; // clear the interrupt?
|
||||
else
|
||||
newVal.intStatus = oldVal.intStatus;
|
||||
if (oldVal.dmaError && newVal.dmaError)
|
||||
newVal.dmaError = 0;
|
||||
else
|
||||
newVal.dmaError = oldVal.dmaError;
|
||||
|
||||
bmiRegs.status = newVal;
|
||||
}
|
||||
break;
|
||||
case BMIDescTablePtr:
|
||||
if (size != sizeof(uint32_t))
|
||||
panic("Invalid BMIDTP write size: %x\n", size);
|
||||
bmiRegs.bmidtp = htole(*(uint32_t *)data & ~0x3);
|
||||
break;
|
||||
default:
|
||||
if (size != sizeof(uint8_t) && size != sizeof(uint16_t) &&
|
||||
size != sizeof(uint32_t))
|
||||
panic("IDE controller write of invalid write size: %x\n", size);
|
||||
memcpy((uint8_t *)&bmiRegs + offset, data, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IdeController::dispatchAccess(PacketPtr pkt, bool read)
|
||||
{
|
||||
pkt->allocate();
|
||||
if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4)
|
||||
panic("Bad IDE read size: %d\n", pkt->getSize());
|
||||
|
||||
if (!ioEnabled) {
|
||||
pkt->makeAtomicResponse();
|
||||
DPRINTF(IdeCtrl, "io not enabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Addr addr = pkt->getAddr();
|
||||
int size = pkt->getSize();
|
||||
uint8_t *dataPtr = pkt->getPtr<uint8_t>();
|
||||
|
||||
if (addr >= primary.cmdAddr &&
|
||||
addr < (primary.cmdAddr + primary.cmdSize)) {
|
||||
addr -= primary.cmdAddr;
|
||||
// linux may have shifted the address by ioShift,
|
||||
// here we shift it back, similarly for ctrlOffset.
|
||||
addr >>= ioShift;
|
||||
primary.accessCommand(addr, size, dataPtr, read);
|
||||
} else if (addr >= primary.ctrlAddr &&
|
||||
addr < (primary.ctrlAddr + primary.ctrlSize)) {
|
||||
addr -= primary.ctrlAddr;
|
||||
addr += ctrlOffset;
|
||||
primary.accessControl(addr, size, dataPtr, read);
|
||||
} else if (addr >= secondary.cmdAddr &&
|
||||
addr < (secondary.cmdAddr + secondary.cmdSize)) {
|
||||
addr -= secondary.cmdAddr;
|
||||
secondary.accessCommand(addr, size, dataPtr, read);
|
||||
} else if (addr >= secondary.ctrlAddr &&
|
||||
addr < (secondary.ctrlAddr + secondary.ctrlSize)) {
|
||||
addr -= secondary.ctrlAddr;
|
||||
secondary.accessControl(addr, size, dataPtr, read);
|
||||
} else if (addr >= bmiAddr && addr < (bmiAddr + bmiSize)) {
|
||||
if (!read && !bmEnabled)
|
||||
return;
|
||||
addr -= bmiAddr;
|
||||
if (addr < sizeof(Channel::BMIRegs)) {
|
||||
primary.accessBMI(addr, size, dataPtr, read);
|
||||
} else {
|
||||
addr -= sizeof(Channel::BMIRegs);
|
||||
secondary.accessBMI(addr, size, dataPtr, read);
|
||||
}
|
||||
} else {
|
||||
panic("IDE controller access to invalid address: %#x\n", addr);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
uint32_t data;
|
||||
if (pkt->getSize() == 1)
|
||||
data = pkt->get<uint8_t>();
|
||||
else if (pkt->getSize() == 2)
|
||||
data = pkt->get<uint16_t>();
|
||||
else
|
||||
data = pkt->get<uint32_t>();
|
||||
DPRINTF(IdeCtrl, "%s from offset: %#x size: %#x data: %#x\n",
|
||||
read ? "Read" : "Write", pkt->getAddr(), pkt->getSize(), data);
|
||||
#endif
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
}
|
||||
|
||||
Tick
|
||||
IdeController::read(PacketPtr pkt)
|
||||
{
|
||||
dispatchAccess(pkt, true);
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
IdeController::write(PacketPtr pkt)
|
||||
{
|
||||
dispatchAccess(pkt, false);
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
IdeController::serialize(std::ostream &os)
|
||||
{
|
||||
// Serialize the PciDev base class
|
||||
PciDev::serialize(os);
|
||||
|
||||
// Serialize channels
|
||||
primary.serialize("primary", os);
|
||||
secondary.serialize("secondary", os);
|
||||
|
||||
// Serialize config registers
|
||||
SERIALIZE_SCALAR(primaryTiming);
|
||||
SERIALIZE_SCALAR(secondaryTiming);
|
||||
SERIALIZE_SCALAR(deviceTiming);
|
||||
SERIALIZE_SCALAR(udmaControl);
|
||||
SERIALIZE_SCALAR(udmaTiming);
|
||||
SERIALIZE_SCALAR(ideConfig);
|
||||
|
||||
// Serialize internal state
|
||||
SERIALIZE_SCALAR(ioEnabled);
|
||||
SERIALIZE_SCALAR(bmEnabled);
|
||||
SERIALIZE_SCALAR(bmiAddr);
|
||||
SERIALIZE_SCALAR(bmiSize);
|
||||
}
|
||||
|
||||
void
|
||||
IdeController::Channel::serialize(const std::string &base, std::ostream &os)
|
||||
{
|
||||
paramOut(os, base + ".cmdAddr", cmdAddr);
|
||||
paramOut(os, base + ".cmdSize", cmdSize);
|
||||
paramOut(os, base + ".ctrlAddr", ctrlAddr);
|
||||
paramOut(os, base + ".ctrlSize", ctrlSize);
|
||||
uint8_t command = bmiRegs.command;
|
||||
paramOut(os, base + ".bmiRegs.command", command);
|
||||
paramOut(os, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
|
||||
uint8_t status = bmiRegs.status;
|
||||
paramOut(os, base + ".bmiRegs.status", status);
|
||||
paramOut(os, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
|
||||
paramOut(os, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
|
||||
paramOut(os, base + ".selectBit", selectBit);
|
||||
}
|
||||
|
||||
void
|
||||
IdeController::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
// Unserialize the PciDev base class
|
||||
PciDev::unserialize(cp, section);
|
||||
|
||||
// Unserialize channels
|
||||
primary.unserialize("primary", cp, section);
|
||||
secondary.unserialize("secondary", cp, section);
|
||||
|
||||
// Unserialize config registers
|
||||
UNSERIALIZE_SCALAR(primaryTiming);
|
||||
UNSERIALIZE_SCALAR(secondaryTiming);
|
||||
UNSERIALIZE_SCALAR(deviceTiming);
|
||||
UNSERIALIZE_SCALAR(udmaControl);
|
||||
UNSERIALIZE_SCALAR(udmaTiming);
|
||||
UNSERIALIZE_SCALAR(ideConfig);
|
||||
|
||||
// Unserialize internal state
|
||||
UNSERIALIZE_SCALAR(ioEnabled);
|
||||
UNSERIALIZE_SCALAR(bmEnabled);
|
||||
UNSERIALIZE_SCALAR(bmiAddr);
|
||||
UNSERIALIZE_SCALAR(bmiSize);
|
||||
}
|
||||
|
||||
void
|
||||
IdeController::Channel::unserialize(const std::string &base, Checkpoint *cp,
|
||||
const std::string §ion)
|
||||
{
|
||||
paramIn(cp, section, base + ".cmdAddr", cmdAddr);
|
||||
paramIn(cp, section, base + ".cmdSize", cmdSize);
|
||||
paramIn(cp, section, base + ".ctrlAddr", ctrlAddr);
|
||||
paramIn(cp, section, base + ".ctrlSize", ctrlSize);
|
||||
uint8_t command;
|
||||
paramIn(cp, section, base +".bmiRegs.command", command);
|
||||
bmiRegs.command = command;
|
||||
paramIn(cp, section, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
|
||||
uint8_t status;
|
||||
paramIn(cp, section, base + ".bmiRegs.status", status);
|
||||
bmiRegs.status = status;
|
||||
paramIn(cp, section, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
|
||||
paramIn(cp, section, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
|
||||
paramIn(cp, section, base + ".selectBit", selectBit);
|
||||
select(selectBit);
|
||||
}
|
||||
|
||||
IdeController *
|
||||
IdeControllerParams::create()
|
||||
{
|
||||
return new IdeController(this);
|
||||
}
|
||||
161
simulators/gem5/src/dev/ide_ctrl.hh
Normal file
161
simulators/gem5/src/dev/ide_ctrl.hh
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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: Andrew Schultz
|
||||
* Miguel Serrano
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Simple PCI IDE controller with bus mastering capability and UDMA
|
||||
* modeled after controller in the Intel PIIX4 chip
|
||||
*/
|
||||
|
||||
#ifndef __IDE_CTRL_HH__
|
||||
#define __IDE_CTRL_HH__
|
||||
|
||||
#include "base/bitunion.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "dev/pcidev.hh"
|
||||
#include "dev/pcireg.h"
|
||||
#include "params/IdeController.hh"
|
||||
|
||||
class IdeDisk;
|
||||
|
||||
/**
|
||||
* Device model for an Intel PIIX4 IDE controller
|
||||
*/
|
||||
|
||||
class IdeController : public PciDev
|
||||
{
|
||||
private:
|
||||
// Bus master IDE status register bit fields
|
||||
BitUnion8(BMIStatusReg)
|
||||
Bitfield<6> dmaCap0;
|
||||
Bitfield<5> dmaCap1;
|
||||
Bitfield<2> intStatus;
|
||||
Bitfield<1> dmaError;
|
||||
Bitfield<0> active;
|
||||
EndBitUnion(BMIStatusReg)
|
||||
|
||||
BitUnion8(BMICommandReg)
|
||||
Bitfield<3> rw;
|
||||
Bitfield<0> startStop;
|
||||
EndBitUnion(BMICommandReg)
|
||||
|
||||
struct Channel
|
||||
{
|
||||
std::string _name;
|
||||
|
||||
const std::string
|
||||
name()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
/** Command and control block registers */
|
||||
Addr cmdAddr, cmdSize, ctrlAddr, ctrlSize;
|
||||
|
||||
/** Registers used for bus master interface */
|
||||
struct BMIRegs
|
||||
{
|
||||
BMICommandReg command;
|
||||
uint8_t reserved0;
|
||||
BMIStatusReg status;
|
||||
uint8_t reserved1;
|
||||
uint32_t bmidtp;
|
||||
} bmiRegs;
|
||||
|
||||
/** IDE disks connected to this controller */
|
||||
IdeDisk *master, *slave;
|
||||
|
||||
/** Currently selected disk */
|
||||
IdeDisk *selected;
|
||||
|
||||
bool selectBit;
|
||||
|
||||
void
|
||||
select(bool selSlave)
|
||||
{
|
||||
selectBit = selSlave;
|
||||
selected = selectBit ? slave : master;
|
||||
}
|
||||
|
||||
void accessCommand(Addr offset, int size, uint8_t *data, bool read);
|
||||
void accessControl(Addr offset, int size, uint8_t *data, bool read);
|
||||
void accessBMI(Addr offset, int size, uint8_t *data, bool read);
|
||||
|
||||
Channel(std::string newName, Addr _cmdSize, Addr _ctrlSize);
|
||||
~Channel();
|
||||
|
||||
void serialize(const std::string &base, std::ostream &os);
|
||||
void unserialize(const std::string &base, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
};
|
||||
|
||||
Channel primary;
|
||||
Channel secondary;
|
||||
|
||||
/** Bus master interface (BMI) registers */
|
||||
Addr bmiAddr, bmiSize;
|
||||
|
||||
/** Registers used in device specific PCI configuration */
|
||||
uint16_t primaryTiming, secondaryTiming;
|
||||
uint8_t deviceTiming;
|
||||
uint8_t udmaControl;
|
||||
uint16_t udmaTiming;
|
||||
uint16_t ideConfig;
|
||||
|
||||
// Internal management variables
|
||||
bool ioEnabled;
|
||||
bool bmEnabled;
|
||||
|
||||
uint32_t ioShift, ctrlOffset;
|
||||
|
||||
void dispatchAccess(PacketPtr pkt, bool read);
|
||||
|
||||
public:
|
||||
typedef IdeControllerParams Params;
|
||||
const Params *params() const { return (const Params *)_params; }
|
||||
IdeController(Params *p);
|
||||
|
||||
/** See if a disk is selected based on its pointer */
|
||||
bool isDiskSelected(IdeDisk *diskPtr);
|
||||
|
||||
void intrPost();
|
||||
|
||||
Tick writeConfig(PacketPtr pkt);
|
||||
Tick readConfig(PacketPtr pkt);
|
||||
|
||||
void setDmaComplete(IdeDisk *disk);
|
||||
|
||||
Tick read(PacketPtr pkt);
|
||||
Tick write(PacketPtr pkt);
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
#endif // __IDE_CTRL_HH_
|
||||
1138
simulators/gem5/src/dev/ide_disk.cc
Normal file
1138
simulators/gem5/src/dev/ide_disk.cc
Normal file
File diff suppressed because it is too large
Load Diff
368
simulators/gem5/src/dev/ide_disk.hh
Normal file
368
simulators/gem5/src/dev/ide_disk.hh
Normal file
@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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: Andrew Schultz
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Device model for an IDE disk
|
||||
*/
|
||||
|
||||
#ifndef __IDE_DISK_HH__
|
||||
#define __IDE_DISK_HH__
|
||||
|
||||
#include "base/statistics.hh"
|
||||
#include "dev/disk_image.hh"
|
||||
#include "dev/ide_atareg.h"
|
||||
#include "dev/ide_ctrl.hh"
|
||||
#include "dev/ide_wdcreg.h"
|
||||
#include "dev/io_device.hh"
|
||||
#include "params/IdeDisk.hh"
|
||||
#include "sim/eventq.hh"
|
||||
|
||||
class ChunkGenerator;
|
||||
|
||||
#define DMA_BACKOFF_PERIOD 200
|
||||
|
||||
#define MAX_DMA_SIZE 0x20000 // 128K
|
||||
#define MAX_SINGLE_DMA_SIZE 0x10000
|
||||
#define MAX_MULTSECT (128)
|
||||
|
||||
#define PRD_BASE_MASK 0xfffffffe
|
||||
#define PRD_COUNT_MASK 0xfffe
|
||||
#define PRD_EOT_MASK 0x8000
|
||||
|
||||
typedef struct PrdEntry {
|
||||
uint32_t baseAddr;
|
||||
uint16_t byteCount;
|
||||
uint16_t endOfTable;
|
||||
} PrdEntry_t;
|
||||
|
||||
class PrdTableEntry {
|
||||
public:
|
||||
PrdEntry_t entry;
|
||||
|
||||
uint32_t getBaseAddr()
|
||||
{
|
||||
return (entry.baseAddr & PRD_BASE_MASK);
|
||||
}
|
||||
|
||||
uint32_t getByteCount()
|
||||
{
|
||||
return ((entry.byteCount == 0) ? MAX_SINGLE_DMA_SIZE :
|
||||
(entry.byteCount & PRD_COUNT_MASK));
|
||||
}
|
||||
|
||||
uint16_t getEOT()
|
||||
{
|
||||
return (entry.endOfTable & PRD_EOT_MASK);
|
||||
}
|
||||
};
|
||||
|
||||
#define DATA_OFFSET (0)
|
||||
#define ERROR_OFFSET (1)
|
||||
#define FEATURES_OFFSET (1)
|
||||
#define NSECTOR_OFFSET (2)
|
||||
#define SECTOR_OFFSET (3)
|
||||
#define LCYL_OFFSET (4)
|
||||
#define HCYL_OFFSET (5)
|
||||
#define SELECT_OFFSET (6)
|
||||
#define DRIVE_OFFSET (6)
|
||||
#define STATUS_OFFSET (7)
|
||||
#define COMMAND_OFFSET (7)
|
||||
|
||||
#define CONTROL_OFFSET (2)
|
||||
#define ALTSTAT_OFFSET (2)
|
||||
|
||||
#define SELECT_DEV_BIT 0x10
|
||||
#define CONTROL_RST_BIT 0x04
|
||||
#define CONTROL_IEN_BIT 0x02
|
||||
#define STATUS_BSY_BIT 0x80
|
||||
#define STATUS_DRDY_BIT 0x40
|
||||
#define STATUS_DRQ_BIT 0x08
|
||||
#define STATUS_SEEK_BIT 0x10
|
||||
#define STATUS_DF_BIT 0x20
|
||||
#define DRIVE_LBA_BIT 0x40
|
||||
|
||||
#define DEV0 (0)
|
||||
#define DEV1 (1)
|
||||
|
||||
typedef struct CommandReg {
|
||||
uint16_t data;
|
||||
uint8_t error;
|
||||
uint8_t sec_count;
|
||||
uint8_t sec_num;
|
||||
uint8_t cyl_low;
|
||||
uint8_t cyl_high;
|
||||
union {
|
||||
uint8_t drive;
|
||||
uint8_t head;
|
||||
};
|
||||
uint8_t command;
|
||||
} CommandReg_t;
|
||||
|
||||
typedef enum Events {
|
||||
None = 0,
|
||||
Transfer,
|
||||
ReadWait,
|
||||
WriteWait,
|
||||
PrdRead,
|
||||
DmaRead,
|
||||
DmaWrite
|
||||
} Events_t;
|
||||
|
||||
typedef enum DevAction {
|
||||
ACT_NONE = 0,
|
||||
ACT_CMD_WRITE,
|
||||
ACT_CMD_COMPLETE,
|
||||
ACT_CMD_ERROR,
|
||||
ACT_SELECT_WRITE,
|
||||
ACT_STAT_READ,
|
||||
ACT_DATA_READY,
|
||||
ACT_DATA_READ_BYTE,
|
||||
ACT_DATA_READ_SHORT,
|
||||
ACT_DATA_WRITE_BYTE,
|
||||
ACT_DATA_WRITE_SHORT,
|
||||
ACT_DMA_READY,
|
||||
ACT_DMA_DONE,
|
||||
ACT_SRST_SET,
|
||||
ACT_SRST_CLEAR
|
||||
} DevAction_t;
|
||||
|
||||
typedef enum DevState {
|
||||
// Device idle
|
||||
Device_Idle_S = 0,
|
||||
Device_Idle_SI,
|
||||
Device_Idle_NS,
|
||||
|
||||
// Software reset
|
||||
Device_Srst,
|
||||
|
||||
// Non-data commands
|
||||
Command_Execution,
|
||||
|
||||
// PIO data-in (data to host)
|
||||
Prepare_Data_In,
|
||||
Data_Ready_INTRQ_In,
|
||||
Transfer_Data_In,
|
||||
|
||||
// PIO data-out (data from host)
|
||||
Prepare_Data_Out,
|
||||
Data_Ready_INTRQ_Out,
|
||||
Transfer_Data_Out,
|
||||
|
||||
// DMA protocol
|
||||
Prepare_Data_Dma,
|
||||
Transfer_Data_Dma
|
||||
} DevState_t;
|
||||
|
||||
typedef enum DmaState {
|
||||
Dma_Idle = 0,
|
||||
Dma_Start,
|
||||
Dma_Transfer
|
||||
} DmaState_t;
|
||||
|
||||
class IdeController;
|
||||
|
||||
/**
|
||||
* IDE Disk device model
|
||||
*/
|
||||
class IdeDisk : public SimObject
|
||||
{
|
||||
protected:
|
||||
/** The IDE controller for this disk. */
|
||||
IdeController *ctrl;
|
||||
/** The image that contains the data of this disk. */
|
||||
DiskImage *image;
|
||||
|
||||
protected:
|
||||
/** The disk delay in microseconds. */
|
||||
int diskDelay;
|
||||
|
||||
private:
|
||||
/** Drive identification structure for this disk */
|
||||
struct ataparams driveID;
|
||||
/** Data buffer for transfers */
|
||||
uint8_t *dataBuffer;
|
||||
/** Number of bytes in command data transfer */
|
||||
uint32_t cmdBytes;
|
||||
/** Number of bytes left in command data transfer */
|
||||
uint32_t cmdBytesLeft;
|
||||
/** Number of bytes left in DRQ block */
|
||||
uint32_t drqBytesLeft;
|
||||
/** Current sector in access */
|
||||
uint32_t curSector;
|
||||
/** Command block registers */
|
||||
CommandReg_t cmdReg;
|
||||
/** Status register */
|
||||
uint8_t status;
|
||||
/** Interrupt enable bit */
|
||||
bool nIENBit;
|
||||
/** Device state */
|
||||
DevState_t devState;
|
||||
/** Dma state */
|
||||
DmaState_t dmaState;
|
||||
/** Dma transaction is a read */
|
||||
bool dmaRead;
|
||||
/** PRD table base address */
|
||||
uint32_t curPrdAddr;
|
||||
/** PRD entry */
|
||||
PrdTableEntry curPrd;
|
||||
/** Device ID (master=0/slave=1) */
|
||||
int devID;
|
||||
/** Interrupt pending */
|
||||
bool intrPending;
|
||||
|
||||
Stats::Scalar dmaReadFullPages;
|
||||
Stats::Scalar dmaReadBytes;
|
||||
Stats::Scalar dmaReadTxs;
|
||||
Stats::Scalar dmaWriteFullPages;
|
||||
Stats::Scalar dmaWriteBytes;
|
||||
Stats::Scalar dmaWriteTxs;
|
||||
|
||||
public:
|
||||
typedef IdeDiskParams Params;
|
||||
IdeDisk(const Params *p);
|
||||
|
||||
/**
|
||||
* Delete the data buffer.
|
||||
*/
|
||||
~IdeDisk();
|
||||
|
||||
/**
|
||||
* Reset the device state
|
||||
*/
|
||||
void reset(int id);
|
||||
|
||||
/**
|
||||
* Register Statistics
|
||||
*/
|
||||
void regStats();
|
||||
|
||||
/**
|
||||
* Set the controller for this device
|
||||
* @param c The IDE controller
|
||||
*/
|
||||
void setController(IdeController *c) {
|
||||
if (ctrl) panic("Cannot change the controller once set!\n");
|
||||
ctrl = c;
|
||||
}
|
||||
|
||||
// Device register read/write
|
||||
void readCommand(const Addr offset, int size, uint8_t *data);
|
||||
void readControl(const Addr offset, int size, uint8_t *data);
|
||||
void writeCommand(const Addr offset, int size, const uint8_t *data);
|
||||
void writeControl(const Addr offset, int size, const uint8_t *data);
|
||||
|
||||
// Start/abort functions
|
||||
void startDma(const uint32_t &prdTableBase);
|
||||
void abortDma();
|
||||
|
||||
private:
|
||||
void startCommand();
|
||||
|
||||
// Interrupt management
|
||||
void intrPost();
|
||||
void intrClear();
|
||||
|
||||
// DMA stuff
|
||||
void doDmaTransfer();
|
||||
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>;
|
||||
EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent;
|
||||
|
||||
void doDmaDataRead();
|
||||
|
||||
void doDmaRead();
|
||||
ChunkGenerator *dmaReadCG;
|
||||
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>;
|
||||
EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent;
|
||||
|
||||
void doDmaDataWrite();
|
||||
|
||||
void doDmaWrite();
|
||||
ChunkGenerator *dmaWriteCG;
|
||||
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>;
|
||||
EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent;
|
||||
|
||||
void dmaPrdReadDone();
|
||||
friend class EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone>;
|
||||
EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone> dmaPrdReadEvent;
|
||||
|
||||
void dmaReadDone();
|
||||
friend class EventWrapper<IdeDisk, &IdeDisk::dmaReadDone>;
|
||||
EventWrapper<IdeDisk, &IdeDisk::dmaReadDone> dmaReadEvent;
|
||||
|
||||
void dmaWriteDone();
|
||||
friend class EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone>;
|
||||
EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone> dmaWriteEvent;
|
||||
|
||||
// Disk image read/write
|
||||
void readDisk(uint32_t sector, uint8_t *data);
|
||||
void writeDisk(uint32_t sector, uint8_t *data);
|
||||
|
||||
// State machine management
|
||||
void updateState(DevAction_t action);
|
||||
|
||||
// Utility functions
|
||||
bool isBSYSet() { return (status & STATUS_BSY_BIT); }
|
||||
bool isIENSet() { return nIENBit; }
|
||||
bool isDEVSelect();
|
||||
|
||||
void setComplete()
|
||||
{
|
||||
// clear out the status byte
|
||||
status = 0;
|
||||
// set the DRDY bit
|
||||
status |= STATUS_DRDY_BIT;
|
||||
// set the SEEK bit
|
||||
status |= STATUS_SEEK_BIT;
|
||||
}
|
||||
|
||||
uint32_t getLBABase()
|
||||
{
|
||||
return (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) |
|
||||
(cmdReg.cyl_low << 8) | (cmdReg.sec_num));
|
||||
}
|
||||
|
||||
inline Addr pciToDma(Addr pciAddr);
|
||||
|
||||
/**
|
||||
* Serialize this object to the given output stream.
|
||||
* @param os The stream to serialize to.
|
||||
*/
|
||||
void serialize(std::ostream &os);
|
||||
|
||||
/**
|
||||
* Reconstruct the state of this object from a checkpoint.
|
||||
* @param cp The checkpoint to use.
|
||||
* @param section The section name describing this object.
|
||||
*/
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
|
||||
#endif // __IDE_DISK_HH__
|
||||
197
simulators/gem5/src/dev/ide_wdcreg.h
Normal file
197
simulators/gem5/src/dev/ide_wdcreg.h
Normal file
@ -0,0 +1,197 @@
|
||||
/* $OpenBSD: wdcreg.h,v 1.13 2004/09/24 07:05:44 grange Exp $ */
|
||||
/* $NetBSD: wdcreg.h,v 1.22 1999/03/07 14:02:54 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California
|
||||
* All rights reserved
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* William Jolitz.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)wdreg.h 7.1 (Berkeley) 5/9/91
|
||||
*/
|
||||
|
||||
#ifndef _DEV_IC_WDCREG_H_
|
||||
#define _DEV_IC_WDCREG_H_
|
||||
|
||||
/*
|
||||
* Controller register (wdr_ctlr)
|
||||
*/
|
||||
#define WDCTL_4BIT 0x08 /* use four head bits (wd1003) */
|
||||
#define WDCTL_RST 0x04 /* reset the controller */
|
||||
#define WDCTL_IDS 0x02 /* disable controller interrupts */
|
||||
|
||||
/*
|
||||
* Status bits.
|
||||
*/
|
||||
#define WDCS_BSY 0x80 /* busy */
|
||||
#define WDCS_DRDY 0x40 /* drive ready */
|
||||
#define WDCS_DWF 0x20 /* drive write fault */
|
||||
#define WDCS_DSC 0x10 /* drive seek complete */
|
||||
#define WDCS_DRQ 0x08 /* data request */
|
||||
#define WDCS_CORR 0x04 /* corrected data */
|
||||
#define WDCS_IDX 0x02 /* index */
|
||||
#define WDCS_ERR 0x01 /* error */
|
||||
#define WDCS_BITS "\020\010BSY\007DRDY\006DWF\005DSC\004DRQ\003CORR\002IDX\001ERR"
|
||||
|
||||
/*
|
||||
* Error bits.
|
||||
*/
|
||||
#define WDCE_BBK 0x80 /* bad block detected */
|
||||
#define WDCE_CRC 0x80 /* CRC error (Ultra-DMA only) */
|
||||
#define WDCE_UNC 0x40 /* uncorrectable data error */
|
||||
#define WDCE_MC 0x20 /* media changed */
|
||||
#define WDCE_IDNF 0x10 /* id not found */
|
||||
#define WDCE_MCR 0x08 /* media change requested */
|
||||
#define WDCE_ABRT 0x04 /* aborted command */
|
||||
#define WDCE_TK0NF 0x02 /* track 0 not found */
|
||||
#define WDCE_AMNF 0x01 /* address mark not found */
|
||||
|
||||
/*
|
||||
* Commands for Disk Controller.
|
||||
*/
|
||||
#define WDCC_NOP 0x00 /* NOP - Always fail with "aborted command" */
|
||||
#define WDCC_RECAL 0x10 /* disk restore code -- resets cntlr */
|
||||
|
||||
#define WDCC_READ 0x20 /* disk read code */
|
||||
#define WDCC_WRITE 0x30 /* disk write code */
|
||||
#define WDCC__LONG 0x02 /* modifier -- access ecc bytes */
|
||||
#define WDCC__NORETRY 0x01 /* modifier -- no retrys */
|
||||
|
||||
#define WDCC_FORMAT 0x50 /* disk format code */
|
||||
#define WDCC_DIAGNOSE 0x90 /* controller diagnostic */
|
||||
#define WDCC_IDP 0x91 /* initialize drive parameters */
|
||||
|
||||
#define WDCC_READMULTI 0xc4 /* read multiple */
|
||||
#define WDCC_WRITEMULTI 0xc5 /* write multiple */
|
||||
#define WDCC_SETMULTI 0xc6 /* set multiple mode */
|
||||
|
||||
#define WDCC_READDMA 0xc8 /* read with DMA */
|
||||
#define WDCC_WRITEDMA 0xca /* write with DMA */
|
||||
|
||||
#define WDCC_ACKMC 0xdb /* acknowledge media change */
|
||||
#define WDCC_LOCK 0xde /* lock drawer */
|
||||
#define WDCC_UNLOCK 0xdf /* unlock drawer */
|
||||
|
||||
#define WDCC_FLUSHCACHE 0xe7 /* Flush cache */
|
||||
#define WDCC_IDENTIFY 0xec /* read parameters from controller */
|
||||
#define SET_FEATURES 0xef /* set features */
|
||||
|
||||
#define WDCC_IDLE 0xe3 /* set idle timer & enter idle mode */
|
||||
#define WDCC_IDLE_IMMED 0xe1 /* enter idle mode */
|
||||
#define WDCC_SLEEP 0xe6 /* enter sleep mode */
|
||||
#define WDCC_STANDBY 0xe2 /* set standby timer & enter standby mode */
|
||||
#define WDCC_STANDBY_IMMED 0xe0 /* enter standby mode */
|
||||
#define WDCC_CHECK_PWR 0xe5 /* check power mode */
|
||||
|
||||
#define WDCC_READ_EXT 0x24 /* read 48-bit addressing */
|
||||
#define WDCC_WRITE_EXT 0x34 /* write 48-bit addressing */
|
||||
|
||||
#define WDCC_READMULTI_EXT 0x29 /* read multiple 48-bit addressing */
|
||||
#define WDCC_WRITEMULTI_EXT 0x39 /* write multiple 48-bit addressing */
|
||||
|
||||
#define WDCC_READDMA_EXT 0x25 /* read 48-bit addressing with DMA */
|
||||
#define WDCC_WRITEDMA_EXT 0x35 /* write 48-bit addressing with DMA */
|
||||
|
||||
#define WDCC_FLUSHCACHE_EXT 0xea /* 48-bit addressing flush cache */
|
||||
|
||||
/* Subcommands for SET_FEATURES (features register ) */
|
||||
#define WDSF_8BIT_PIO_EN 0x01 /* Enable 8bit PIO (CFA featureset) */
|
||||
#define WDSF_EN_WR_CACHE 0x02
|
||||
#define WDSF_SET_MODE 0x03
|
||||
#define WDSF_REASSIGN_EN 0x04 /* Obsolete in ATA-6 */
|
||||
#define WDSF_APM_EN 0x05 /* Enable Adv. Power Management */
|
||||
#define WDSF_PUIS_EN 0x06 /* Enable Power-Up In Standby */
|
||||
#define WDSF_PUIS_SPINUP 0x07 /* Power-Up In Standby spin-up */
|
||||
#define WDSF_CFA_MODE1_EN 0x0A /* Enable CFA power mode 1 */
|
||||
#define WDSF_RMSN_DS 0x31 /* Disable Removable Media Status */
|
||||
#define WDSF_RETRY_DS 0x33 /* Obsolete in ATA-6 */
|
||||
#define WDSF_AAM_EN 0x42 /* Enable Autom. Acoustic Management */
|
||||
#define WDSF_SET_CACHE_SGMT 0x54 /* Obsolete in ATA-6 */
|
||||
#define WDSF_READAHEAD_DS 0x55 /* Disable read look-ahead */
|
||||
#define WDSF_RLSE_EN 0x5D /* Enable release interrupt */
|
||||
#define WDSF_SRV_EN 0x5E /* Enable SERVICE interrupt */
|
||||
#define WDSF_POD_DS 0x66
|
||||
#define WDSF_ECC_DS 0x77
|
||||
#define WDSF_8BIT_PIO_DS 0x81 /* Disable 8bit PIO (CFA featureset) */
|
||||
#define WDSF_WRITE_CACHE_DS 0x82
|
||||
#define WDSF_REASSIGN_DS 0x84
|
||||
#define WDSF_APM_DS 0x85 /* Disable Adv. Power Management */
|
||||
#define WDSF_PUIS_DS 0x86 /* Disable Power-Up In Standby */
|
||||
#define WDSF_ECC_EN 0x88
|
||||
#define WDSF_CFA_MODE1_DS 0x8A /* Disable CFA power mode 1 */
|
||||
#define WDSF_RMSN_EN 0x95 /* Enable Removable Media Status */
|
||||
#define WDSF_RETRY_EN 0x99 /* Obsolete in ATA-6 */
|
||||
#define WDSF_SET_CURRENT 0x9A /* Obsolete in ATA-6 */
|
||||
#define WDSF_READAHEAD_EN 0xAA
|
||||
#define WDSF_PREFETCH_SET 0xAB /* Obsolete in ATA-6 */
|
||||
#define WDSF_AAM_DS 0xC2 /* Disable Autom. Acoustic Management */
|
||||
#define WDSF_POD_EN 0xCC
|
||||
#define WDSF_RLSE_DS 0xDD /* Disable release interrupt */
|
||||
#define WDSF_SRV_DS 0xDE /* Disable SERVICE interrupt */
|
||||
#define WDSF_READ_NATIVE_MAX 0xF8
|
||||
#define WDSF_SEEK 0x70
|
||||
#define WDSF_VERIFY 0x40
|
||||
|
||||
/* parameters uploaded to device/heads register */
|
||||
#define WDSD_IBM 0xa0 /* forced to 512 byte sector, ecc */
|
||||
#define WDSD_CHS 0x00 /* cylinder/head/sector addressing */
|
||||
#define WDSD_LBA 0x40 /* logical block addressing */
|
||||
|
||||
/* Commands for ATAPI devices */
|
||||
#define ATAPI_CHECK_POWER_MODE 0xe5
|
||||
#define ATAPI_EXEC_DRIVE_DIAGS 0x90
|
||||
#define ATAPI_IDLE_IMMEDIATE 0xe1
|
||||
#define ATAPI_NOP 0x00
|
||||
#define ATAPI_PKT_CMD 0xa0
|
||||
#define ATAPI_IDENTIFY_DEVICE 0xa1
|
||||
#define ATAPI_SOFT_RESET 0x08
|
||||
#define ATAPI_DEVICE_RESET 0x08 /* ATA/ATAPI-5 name for soft reset */
|
||||
#define ATAPI_SLEEP 0xe6
|
||||
#define ATAPI_STANDBY_IMMEDIATE 0xe0
|
||||
#define ATAPI_SMART 0xB0 /* SMART operations */
|
||||
#define ATAPI_SETMAX 0xF9 /* Set Max Address */
|
||||
#define ATAPI_WRITEEXT 0x34 /* Write sectors Ext */
|
||||
#define ATAPI_SETMAXEXT 0x37 /* Set Max Address Ext */
|
||||
#define ATAPI_WRITEMULTIEXT 0x39 /* Write Multi Ext */
|
||||
|
||||
/* Bytes used by ATAPI_PACKET_COMMAND ( feature register) */
|
||||
#define ATAPI_PKT_CMD_FTRE_DMA 0x01
|
||||
#define ATAPI_PKT_CMD_FTRE_OVL 0x02
|
||||
|
||||
/* ireason */
|
||||
#define WDCI_CMD 0x01 /* command(1) or data(0) */
|
||||
#define WDCI_IN 0x02 /* transfer to(1) or from(0) the host */
|
||||
#define WDCI_RELEASE 0x04 /* bus released until completion */
|
||||
|
||||
#define PHASE_CMDOUT (WDCS_DRQ | WDCI_CMD)
|
||||
#define PHASE_DATAIN (WDCS_DRQ | WDCI_IN)
|
||||
#define PHASE_DATAOUT WDCS_DRQ
|
||||
#define PHASE_COMPLETED (WDCI_IN | WDCI_CMD)
|
||||
#define PHASE_ABORTED 0
|
||||
|
||||
#endif /* !_DEV_IC_WDCREG_H_ */
|
||||
304
simulators/gem5/src/dev/intel_8254_timer.cc
Normal file
304
simulators/gem5/src/dev/intel_8254_timer.cc
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2005
|
||||
* The Regents of The University of Michigan
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This code is part of the M5 simulator.
|
||||
*
|
||||
* Permission is granted to use, copy, create derivative works and
|
||||
* redistribute this software and such derivative works for any
|
||||
* purpose, so long as the copyright notice above, this grant of
|
||||
* permission, and the disclaimer below appear in all copies made; and
|
||||
* so long as the name of The University of Michigan is not used in
|
||||
* any advertising or publicity pertaining to the use or distribution
|
||||
* of this software without specific, written prior authorization.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
|
||||
* UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
|
||||
* WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
|
||||
* LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
|
||||
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
|
||||
* ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
|
||||
* IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGES.
|
||||
*
|
||||
* Authors: Ali G. Saidi
|
||||
* Andrew L. Schultz
|
||||
* Miguel J. Serrano
|
||||
*/
|
||||
|
||||
#include "base/misc.hh"
|
||||
#include "debug/Intel8254Timer.hh"
|
||||
#include "dev/intel_8254_timer.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
Intel8254Timer::Intel8254Timer(EventManager *em, const string &name,
|
||||
Counter *counter0, Counter *counter1, Counter *counter2) :
|
||||
EventManager(em), _name(name)
|
||||
{
|
||||
counter[0] = counter0;
|
||||
counter[1] = counter1;
|
||||
counter[2] = counter2;
|
||||
}
|
||||
|
||||
Intel8254Timer::Intel8254Timer(EventManager *em, const string &name) :
|
||||
EventManager(em), _name(name)
|
||||
{
|
||||
counter[0] = new Counter(this, name + ".counter0", 0);
|
||||
counter[1] = new Counter(this, name + ".counter1", 1);
|
||||
counter[2] = new Counter(this, name + ".counter2", 2);
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::writeControl(const CtrlReg data)
|
||||
{
|
||||
int sel = data.sel;
|
||||
|
||||
if (sel == ReadBackCommand)
|
||||
panic("PITimer Read-Back Command is not implemented.\n");
|
||||
|
||||
if (data.rw == LatchCommand)
|
||||
counter[sel]->latchCount();
|
||||
else {
|
||||
counter[sel]->setRW(data.rw);
|
||||
counter[sel]->setMode(data.mode);
|
||||
counter[sel]->setBCD(data.bcd);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::serialize(const string &base, ostream &os)
|
||||
{
|
||||
// serialize the counters
|
||||
counter[0]->serialize(base + ".counter0", os);
|
||||
counter[1]->serialize(base + ".counter1", os);
|
||||
counter[2]->serialize(base + ".counter2", os);
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::unserialize(const string &base, Checkpoint *cp,
|
||||
const string §ion)
|
||||
{
|
||||
// unserialze the counters
|
||||
counter[0]->unserialize(base + ".counter0", cp, section);
|
||||
counter[1]->unserialize(base + ".counter1", cp, section);
|
||||
counter[2]->unserialize(base + ".counter2", cp, section);
|
||||
}
|
||||
|
||||
Intel8254Timer::Counter::Counter(Intel8254Timer *p,
|
||||
const string &name, unsigned int _num)
|
||||
: _name(name), num(_num), event(this), initial_count(0),
|
||||
latched_count(0), period(0), mode(0), output_high(false),
|
||||
latch_on(false), read_byte(LSB), write_byte(LSB), parent(p)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::Counter::latchCount()
|
||||
{
|
||||
// behave like a real latch
|
||||
if(!latch_on) {
|
||||
latch_on = true;
|
||||
read_byte = LSB;
|
||||
latched_count = currentCount();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Intel8254Timer::Counter::currentCount()
|
||||
{
|
||||
int clocks = event.clocksLeft();
|
||||
if (clocks == -1) {
|
||||
warn_once("Reading current count from inactive timer.\n");
|
||||
return 0;
|
||||
}
|
||||
if (mode == RateGen || mode == SquareWave)
|
||||
return clocks + 1;
|
||||
else
|
||||
return clocks;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
Intel8254Timer::Counter::read()
|
||||
{
|
||||
if (latch_on) {
|
||||
switch (read_byte) {
|
||||
case LSB:
|
||||
read_byte = MSB;
|
||||
return (uint8_t)latched_count;
|
||||
break;
|
||||
case MSB:
|
||||
read_byte = LSB;
|
||||
latch_on = false;
|
||||
return latched_count >> 8;
|
||||
break;
|
||||
default:
|
||||
panic("Shouldn't be here");
|
||||
}
|
||||
} else {
|
||||
uint16_t count = currentCount();
|
||||
switch (read_byte) {
|
||||
case LSB:
|
||||
read_byte = MSB;
|
||||
return (uint8_t)count;
|
||||
break;
|
||||
case MSB:
|
||||
read_byte = LSB;
|
||||
return count >> 8;
|
||||
break;
|
||||
default:
|
||||
panic("Shouldn't be here");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::Counter::write(const uint8_t data)
|
||||
{
|
||||
switch (write_byte) {
|
||||
case LSB:
|
||||
initial_count = (initial_count & 0xFF00) | data;
|
||||
|
||||
if (event.scheduled())
|
||||
parent->deschedule(event);
|
||||
output_high = false;
|
||||
write_byte = MSB;
|
||||
break;
|
||||
|
||||
case MSB:
|
||||
initial_count = (initial_count & 0x00FF) | (data << 8);
|
||||
// In the RateGen or SquareWave modes, the timer wraps around and
|
||||
// triggers on a value of 1, not 0.
|
||||
if (mode == RateGen || mode == SquareWave)
|
||||
period = initial_count - 1;
|
||||
else
|
||||
period = initial_count;
|
||||
|
||||
if (period > 0)
|
||||
event.setTo(period);
|
||||
|
||||
write_byte = LSB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::Counter::setRW(int rw_val)
|
||||
{
|
||||
if (rw_val != TwoPhase)
|
||||
panic("Only LSB/MSB read/write is implemented.\n");
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::Counter::setMode(int mode_val)
|
||||
{
|
||||
if(mode_val != InitTc && mode_val != RateGen &&
|
||||
mode_val != SquareWave)
|
||||
panic("PIT mode %#x is not implemented: \n", mode_val);
|
||||
|
||||
mode = mode_val;
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::Counter::setBCD(int bcd_val)
|
||||
{
|
||||
if (bcd_val)
|
||||
panic("PITimer does not implement BCD counts.\n");
|
||||
}
|
||||
|
||||
bool
|
||||
Intel8254Timer::Counter::outputHigh()
|
||||
{
|
||||
return output_high;
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::Counter::serialize(const string &base, ostream &os)
|
||||
{
|
||||
paramOut(os, base + ".initial_count", initial_count);
|
||||
paramOut(os, base + ".latched_count", latched_count);
|
||||
paramOut(os, base + ".period", period);
|
||||
paramOut(os, base + ".mode", mode);
|
||||
paramOut(os, base + ".output_high", output_high);
|
||||
paramOut(os, base + ".latch_on", latch_on);
|
||||
paramOut(os, base + ".read_byte", read_byte);
|
||||
paramOut(os, base + ".write_byte", write_byte);
|
||||
|
||||
Tick event_tick = 0;
|
||||
if (event.scheduled())
|
||||
event_tick = event.when();
|
||||
paramOut(os, base + ".event_tick", event_tick);
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp,
|
||||
const string §ion)
|
||||
{
|
||||
paramIn(cp, section, base + ".initial_count", initial_count);
|
||||
paramIn(cp, section, base + ".latched_count", latched_count);
|
||||
paramIn(cp, section, base + ".period", period);
|
||||
paramIn(cp, section, base + ".mode", mode);
|
||||
paramIn(cp, section, base + ".output_high", output_high);
|
||||
paramIn(cp, section, base + ".latch_on", latch_on);
|
||||
paramIn(cp, section, base + ".read_byte", read_byte);
|
||||
paramIn(cp, section, base + ".write_byte", write_byte);
|
||||
|
||||
Tick event_tick = 0;
|
||||
if (event.scheduled())
|
||||
parent->deschedule(event);
|
||||
paramIn(cp, section, base + ".event_tick", event_tick);
|
||||
if (event_tick)
|
||||
parent->schedule(event, event_tick);
|
||||
}
|
||||
|
||||
Intel8254Timer::Counter::CounterEvent::CounterEvent(Counter* c_ptr)
|
||||
{
|
||||
interval = (Tick)(SimClock::Float::s / 1193180.0);
|
||||
counter = c_ptr;
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::Counter::CounterEvent::process()
|
||||
{
|
||||
switch (counter->mode) {
|
||||
case InitTc:
|
||||
counter->output_high = true;
|
||||
break;
|
||||
case RateGen:
|
||||
case SquareWave:
|
||||
setTo(counter->period);
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemented PITimer mode.\n");
|
||||
}
|
||||
counter->parent->counterInterrupt(counter->num);
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::Counter::CounterEvent::setTo(int clocks)
|
||||
{
|
||||
if (clocks == 0)
|
||||
panic("Timer can't be set to go off instantly.\n");
|
||||
DPRINTF(Intel8254Timer, "Timer set to curTick() + %d\n",
|
||||
clocks * interval);
|
||||
counter->parent->schedule(this, curTick() + clocks * interval);
|
||||
}
|
||||
|
||||
int
|
||||
Intel8254Timer::Counter::CounterEvent::clocksLeft()
|
||||
{
|
||||
if (!scheduled())
|
||||
return -1;
|
||||
return (when() - curTick() + interval - 1) / interval;
|
||||
}
|
||||
|
||||
const char *
|
||||
Intel8254Timer::Counter::CounterEvent::description() const
|
||||
{
|
||||
return "Intel 8254 Interval timer";
|
||||
}
|
||||
250
simulators/gem5/src/dev/intel_8254_timer.hh
Normal file
250
simulators/gem5/src/dev/intel_8254_timer.hh
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2005
|
||||
* The Regents of The University of Michigan
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This code is part of the M5 simulator.
|
||||
*
|
||||
* Permission is granted to use, copy, create derivative works and
|
||||
* redistribute this software and such derivative works for any
|
||||
* purpose, so long as the copyright notice above, this grant of
|
||||
* permission, and the disclaimer below appear in all copies made; and
|
||||
* so long as the name of The University of Michigan is not used in
|
||||
* any advertising or publicity pertaining to the use or distribution
|
||||
* of this software without specific, written prior authorization.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
|
||||
* UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
|
||||
* WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
|
||||
* LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
|
||||
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
|
||||
* ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
|
||||
* IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGES.
|
||||
*
|
||||
* Authors: Ali G. Saidi
|
||||
* Andrew L. Schultz
|
||||
* Miguel J. Serrano
|
||||
*/
|
||||
|
||||
#ifndef __DEV_8254_HH__
|
||||
#define __DEV_8254_HH__
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "base/bitunion.hh"
|
||||
#include "base/types.hh"
|
||||
#include "debug/Intel8254Timer.hh"
|
||||
#include "sim/eventq.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
/** Programmable Interval Timer (Intel 8254) */
|
||||
class Intel8254Timer : public EventManager
|
||||
{
|
||||
protected:
|
||||
BitUnion8(CtrlReg)
|
||||
Bitfield<7, 6> sel;
|
||||
Bitfield<5, 4> rw;
|
||||
Bitfield<3, 1> mode;
|
||||
Bitfield<0> bcd;
|
||||
EndBitUnion(CtrlReg)
|
||||
|
||||
enum SelectVal {
|
||||
SelectCounter0,
|
||||
SelectCounter1,
|
||||
SelectCounter2,
|
||||
ReadBackCommand
|
||||
};
|
||||
|
||||
enum ReadWriteVal {
|
||||
LatchCommand,
|
||||
LsbOnly,
|
||||
MsbOnly,
|
||||
TwoPhase
|
||||
};
|
||||
|
||||
enum ModeVal {
|
||||
InitTc,
|
||||
OneShot,
|
||||
RateGen,
|
||||
SquareWave,
|
||||
SoftwareStrobe,
|
||||
HardwareStrobe
|
||||
};
|
||||
|
||||
/** Counter element for PIT */
|
||||
class Counter
|
||||
{
|
||||
/** Event for counter interrupt */
|
||||
class CounterEvent : public Event
|
||||
{
|
||||
private:
|
||||
/** Pointer back to Counter */
|
||||
Counter* counter;
|
||||
Tick interval;
|
||||
|
||||
public:
|
||||
CounterEvent(Counter*);
|
||||
|
||||
/** Event process */
|
||||
void process();
|
||||
|
||||
/** Event description */
|
||||
virtual const char *description() const;
|
||||
|
||||
friend class Counter;
|
||||
|
||||
void setTo(int clocks);
|
||||
|
||||
int clocksLeft();
|
||||
};
|
||||
|
||||
private:
|
||||
std::string _name;
|
||||
const std::string &name() const { return _name; }
|
||||
|
||||
unsigned int num;
|
||||
|
||||
CounterEvent event;
|
||||
|
||||
/** Initial count value */
|
||||
uint16_t initial_count;
|
||||
|
||||
/** Latched count */
|
||||
uint16_t latched_count;
|
||||
|
||||
/** Interrupt period */
|
||||
uint16_t period;
|
||||
|
||||
/** Current mode of operation */
|
||||
uint8_t mode;
|
||||
|
||||
/** Output goes high when the counter reaches zero */
|
||||
bool output_high;
|
||||
|
||||
/** State of the count latch */
|
||||
bool latch_on;
|
||||
|
||||
/** Set of values for read_byte and write_byte */
|
||||
enum {LSB, MSB};
|
||||
|
||||
/** Determine which byte of a 16-bit count value to read/write */
|
||||
uint8_t read_byte, write_byte;
|
||||
|
||||
/** Pointer to container */
|
||||
Intel8254Timer *parent;
|
||||
|
||||
public:
|
||||
Counter(Intel8254Timer *p, const std::string &name, unsigned int num);
|
||||
|
||||
/** Latch the current count (if one is not already latched) */
|
||||
void latchCount();
|
||||
|
||||
/** Get the current count for this counter */
|
||||
int currentCount();
|
||||
|
||||
/** Set the read/write mode */
|
||||
void setRW(int rw_val);
|
||||
|
||||
/** Set operational mode */
|
||||
void setMode(int mode_val);
|
||||
|
||||
/** Set count encoding */
|
||||
void setBCD(int bcd_val);
|
||||
|
||||
/** Read a count byte */
|
||||
uint8_t read();
|
||||
|
||||
/** Write a count byte */
|
||||
void write(const uint8_t data);
|
||||
|
||||
/** Is the output high? */
|
||||
bool outputHigh();
|
||||
|
||||
/**
|
||||
* Serialize this object to the given output stream.
|
||||
* @param base The base name of the counter object.
|
||||
* @param os The stream to serialize to.
|
||||
*/
|
||||
void serialize(const std::string &base, std::ostream &os);
|
||||
|
||||
/**
|
||||
* Reconstruct the state of this object from a checkpoint.
|
||||
* @param base The base name of the counter object.
|
||||
* @param cp The checkpoint use.
|
||||
* @param section The section name of this object
|
||||
*/
|
||||
void unserialize(const std::string &base, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
};
|
||||
|
||||
protected:
|
||||
std::string _name;
|
||||
const std::string &name() const { return _name; }
|
||||
|
||||
/** PIT has three seperate counters */
|
||||
Counter *counter[3];
|
||||
|
||||
virtual void
|
||||
counterInterrupt(unsigned int num)
|
||||
{
|
||||
DPRINTF(Intel8254Timer, "Timer interrupt from counter %d.\n", num);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
virtual
|
||||
~Intel8254Timer()
|
||||
{}
|
||||
|
||||
Intel8254Timer(EventManager *em, const std::string &name,
|
||||
Counter *counter0, Counter *counter1, Counter *counter2);
|
||||
|
||||
Intel8254Timer(EventManager *em, const std::string &name);
|
||||
|
||||
/** Write control word */
|
||||
void writeControl(const CtrlReg data);
|
||||
|
||||
uint8_t
|
||||
readCounter(unsigned int num)
|
||||
{
|
||||
assert(num < 3);
|
||||
return counter[num]->read();
|
||||
}
|
||||
|
||||
void
|
||||
writeCounter(unsigned int num, const uint8_t data)
|
||||
{
|
||||
assert(num < 3);
|
||||
counter[num]->write(data);
|
||||
}
|
||||
|
||||
bool
|
||||
outputHigh(unsigned int num)
|
||||
{
|
||||
assert(num < 3);
|
||||
return counter[num]->outputHigh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize this object to the given output stream.
|
||||
* @param base The base name of the counter object.
|
||||
* @param os The stream to serialize to.
|
||||
*/
|
||||
void serialize(const std::string &base, std::ostream &os);
|
||||
|
||||
/**
|
||||
* Reconstruct the state of this object from a checkpoint.
|
||||
* @param base The base name of the counter object.
|
||||
* @param cp The checkpoint use.
|
||||
* @param section The section name of this object
|
||||
*/
|
||||
void unserialize(const std::string &base, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
};
|
||||
|
||||
#endif // __DEV_8254_HH__
|
||||
116
simulators/gem5/src/dev/io_device.cc
Normal file
116
simulators/gem5/src/dev/io_device.cc
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* 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
|
||||
* Nathan Binkert
|
||||
*/
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "debug/BusAddrRanges.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
PioPort::PioPort(PioDevice *dev)
|
||||
: SimpleTimingPort(dev->name() + "-pio", dev), device(dev)
|
||||
{
|
||||
}
|
||||
|
||||
Tick
|
||||
PioPort::recvAtomic(PacketPtr pkt)
|
||||
{
|
||||
return pkt->isRead() ? device->read(pkt) : device->write(pkt);
|
||||
}
|
||||
|
||||
AddrRangeList
|
||||
PioPort::getAddrRanges()
|
||||
{
|
||||
return device->getAddrRanges();
|
||||
}
|
||||
|
||||
PioDevice::PioDevice(const Params *p)
|
||||
: MemObject(p), sys(p->system), pioPort(this)
|
||||
{}
|
||||
|
||||
PioDevice::~PioDevice()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PioDevice::init()
|
||||
{
|
||||
if (!pioPort.isConnected())
|
||||
panic("Pio port of %s not connected to anything!", name());
|
||||
pioPort.sendRangeChange();
|
||||
}
|
||||
|
||||
SlavePort &
|
||||
PioDevice::getSlavePort(const std::string &if_name, int idx)
|
||||
{
|
||||
if (if_name == "pio") {
|
||||
return pioPort;
|
||||
}
|
||||
return MemObject::getSlavePort(if_name, idx);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PioDevice::drain(Event *de)
|
||||
{
|
||||
unsigned int count;
|
||||
count = pioPort.drain(de);
|
||||
if (count)
|
||||
changeState(Draining);
|
||||
else
|
||||
changeState(Drained);
|
||||
return count;
|
||||
}
|
||||
|
||||
BasicPioDevice::BasicPioDevice(const Params *p)
|
||||
: PioDevice(p), pioAddr(p->pio_addr), pioSize(0),
|
||||
pioDelay(p->pio_latency)
|
||||
{}
|
||||
|
||||
AddrRangeList
|
||||
BasicPioDevice::getAddrRanges()
|
||||
{
|
||||
assert(pioSize != 0);
|
||||
AddrRangeList ranges;
|
||||
DPRINTF(BusAddrRanges, "registering range: %#x-%#x\n", pioAddr, pioSize);
|
||||
ranges.push_back(RangeSize(pioAddr, pioSize));
|
||||
return ranges;
|
||||
}
|
||||
167
simulators/gem5/src/dev/io_device.hh
Normal file
167
simulators/gem5/src/dev/io_device.hh
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Nathan Binkert
|
||||
*/
|
||||
|
||||
#ifndef __DEV_IO_DEVICE_HH__
|
||||
#define __DEV_IO_DEVICE_HH__
|
||||
|
||||
#include "mem/mem_object.hh"
|
||||
#include "mem/tport.hh"
|
||||
#include "params/BasicPioDevice.hh"
|
||||
#include "params/PioDevice.hh"
|
||||
|
||||
class PioDevice;
|
||||
class System;
|
||||
|
||||
/**
|
||||
* The PioPort class is a programmed i/o port that all devices that are
|
||||
* sensitive to an address range use. The port takes all the memory
|
||||
* access types and roles them into one read() and write() call that the device
|
||||
* must respond to. The device must also provide getAddrRanges() function
|
||||
* with which it returns the address ranges it is interested in.
|
||||
*/
|
||||
class PioPort : public SimpleTimingPort
|
||||
{
|
||||
protected:
|
||||
/** The device that this port serves. */
|
||||
PioDevice *device;
|
||||
|
||||
virtual Tick recvAtomic(PacketPtr pkt);
|
||||
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
public:
|
||||
|
||||
PioPort(PioDevice *dev);
|
||||
};
|
||||
|
||||
/**
|
||||
* This device is the base class which all devices senstive to an address range
|
||||
* inherit from. There are three pure virtual functions which all devices must
|
||||
* implement getAddrRanges(), read(), and write(). The magic do choose which
|
||||
* mode we are in, etc is handled by the PioPort so the device doesn't have to
|
||||
* bother.
|
||||
*/
|
||||
class PioDevice : public MemObject
|
||||
{
|
||||
protected:
|
||||
System *sys;
|
||||
|
||||
/** The pioPort that handles the requests for us and provides us requests
|
||||
* that it sees. */
|
||||
PioPort pioPort;
|
||||
|
||||
/**
|
||||
* Every PIO device is obliged to provide an implementation that
|
||||
* returns the address ranges the device responds to.
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
virtual AddrRangeList getAddrRanges() = 0;
|
||||
|
||||
/** Pure virtual function that the device must implement. Called
|
||||
* when a read command is recieved by the port.
|
||||
* @param pkt Packet describing this request
|
||||
* @return number of ticks it took to complete
|
||||
*/
|
||||
virtual Tick read(PacketPtr pkt) = 0;
|
||||
|
||||
/** Pure virtual function that the device must implement. Called when a
|
||||
* write command is recieved by the port.
|
||||
* @param pkt Packet describing this request
|
||||
* @return number of ticks it took to complete
|
||||
*/
|
||||
virtual Tick write(PacketPtr pkt) = 0;
|
||||
|
||||
public:
|
||||
typedef PioDeviceParams Params;
|
||||
PioDevice(const Params *p);
|
||||
virtual ~PioDevice();
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
virtual void init();
|
||||
|
||||
virtual unsigned int drain(Event *de);
|
||||
|
||||
virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1);
|
||||
|
||||
friend class PioPort;
|
||||
|
||||
};
|
||||
|
||||
class BasicPioDevice : public PioDevice
|
||||
{
|
||||
protected:
|
||||
/** Address that the device listens to. */
|
||||
Addr pioAddr;
|
||||
|
||||
/** Size that the device's address range. */
|
||||
Addr pioSize;
|
||||
|
||||
/** Delay that the device experinces on an access. */
|
||||
Tick pioDelay;
|
||||
|
||||
public:
|
||||
typedef BasicPioDeviceParams Params;
|
||||
BasicPioDevice(const Params *p);
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the address ranges that this device responds to.
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
};
|
||||
|
||||
#endif // __DEV_IO_DEVICE_HH__
|
||||
155
simulators/gem5/src/dev/isa_fake.cc
Normal file
155
simulators/gem5/src/dev/isa_fake.cc
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Isa Fake Device implementation
|
||||
*/
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "debug/IsaFake.hh"
|
||||
#include "dev/isa_fake.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
IsaFake::IsaFake(Params *p)
|
||||
: BasicPioDevice(p)
|
||||
{
|
||||
if (!p->ret_bad_addr)
|
||||
pioSize = p->pio_size;
|
||||
|
||||
retData8 = p->ret_data8;
|
||||
retData16 = p->ret_data16;
|
||||
retData32 = p->ret_data32;
|
||||
retData64 = p->ret_data64;
|
||||
}
|
||||
|
||||
Tick
|
||||
IsaFake::read(PacketPtr pkt)
|
||||
{
|
||||
pkt->allocate();
|
||||
pkt->makeAtomicResponse();
|
||||
|
||||
if (params()->warn_access != "")
|
||||
warn("Device %s accessed by read to address %#x size=%d\n",
|
||||
name(), pkt->getAddr(), pkt->getSize());
|
||||
if (params()->ret_bad_addr) {
|
||||
DPRINTF(IsaFake, "read to bad address va=%#x size=%d\n",
|
||||
pkt->getAddr(), pkt->getSize());
|
||||
pkt->setBadAddress();
|
||||
} else {
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
DPRINTF(IsaFake, "read va=%#x size=%d\n",
|
||||
pkt->getAddr(), pkt->getSize());
|
||||
switch (pkt->getSize()) {
|
||||
case sizeof(uint64_t):
|
||||
pkt->set(retData64);
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
pkt->set(retData32);
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
pkt->set(retData16);
|
||||
break;
|
||||
case sizeof(uint8_t):
|
||||
pkt->set(retData8);
|
||||
break;
|
||||
default:
|
||||
if (params()->fake_mem)
|
||||
std::memset(pkt->getPtr<uint8_t>(), 0, pkt->getSize());
|
||||
else
|
||||
panic("invalid access size! Device being accessed by cache?\n");
|
||||
}
|
||||
}
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
IsaFake::write(PacketPtr pkt)
|
||||
{
|
||||
pkt->makeAtomicResponse();
|
||||
if (params()->warn_access != "") {
|
||||
uint64_t data;
|
||||
switch (pkt->getSize()) {
|
||||
case sizeof(uint64_t):
|
||||
data = pkt->get<uint64_t>();
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
data = pkt->get<uint32_t>();
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
data = pkt->get<uint16_t>();
|
||||
break;
|
||||
case sizeof(uint8_t):
|
||||
data = pkt->get<uint8_t>();
|
||||
break;
|
||||
default:
|
||||
panic("invalid access size!\n");
|
||||
}
|
||||
warn("Device %s accessed by write to address %#x size=%d data=%#x\n",
|
||||
name(), pkt->getAddr(), pkt->getSize(), data);
|
||||
}
|
||||
if (params()->ret_bad_addr) {
|
||||
DPRINTF(IsaFake, "write to bad address va=%#x size=%d \n",
|
||||
pkt->getAddr(), pkt->getSize());
|
||||
pkt->setBadAddress();
|
||||
} else {
|
||||
DPRINTF(IsaFake, "write - va=%#x size=%d \n",
|
||||
pkt->getAddr(), pkt->getSize());
|
||||
|
||||
if (params()->update_data) {
|
||||
switch (pkt->getSize()) {
|
||||
case sizeof(uint64_t):
|
||||
retData64 = pkt->get<uint64_t>();
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
retData32 = pkt->get<uint32_t>();
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
retData16 = pkt->get<uint16_t>();
|
||||
break;
|
||||
case sizeof(uint8_t):
|
||||
retData8 = pkt->get<uint8_t>();
|
||||
break;
|
||||
default:
|
||||
panic("invalid access size!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
IsaFake *
|
||||
IsaFakeParams::create()
|
||||
{
|
||||
return new IsaFake(this);
|
||||
}
|
||||
89
simulators/gem5/src/dev/isa_fake.hh
Normal file
89
simulators/gem5/src/dev/isa_fake.hh
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Declaration of a fake device.
|
||||
*/
|
||||
|
||||
#ifndef __ISA_FAKE_HH__
|
||||
#define __ISA_FAKE_HH__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/io_device.hh"
|
||||
// #include "dev/alpha/tsunami.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "params/IsaFake.hh"
|
||||
|
||||
/**
|
||||
* IsaFake is a device that returns, BadAddr, 1 or 0 on all reads and
|
||||
* rites. It is meant to be placed at an address range
|
||||
* so that an mcheck doesn't occur when an os probes a piece of hw
|
||||
* that doesn't exist (e.g. UARTs1-3), or catch requests in the memory system
|
||||
* that have no responders..
|
||||
*/
|
||||
class IsaFake : public BasicPioDevice
|
||||
{
|
||||
protected:
|
||||
uint8_t retData8;
|
||||
uint16_t retData16;
|
||||
uint32_t retData32;
|
||||
uint64_t retData64;
|
||||
|
||||
public:
|
||||
typedef IsaFakeParams Params;
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
/**
|
||||
* The constructor for Isa Fake just registers itself with the MMU.
|
||||
* @param p params structure
|
||||
*/
|
||||
IsaFake(Params *p);
|
||||
|
||||
/**
|
||||
* This read always returns -1.
|
||||
* @param pkt The memory request.
|
||||
* @param data Where to put the data.
|
||||
*/
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* All writes are simply ignored.
|
||||
* @param pkt The memory request.
|
||||
* @param data the data to not write.
|
||||
*/
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
};
|
||||
|
||||
#endif // __ISA_FAKE_HH__
|
||||
265
simulators/gem5/src/dev/mc146818.cc
Normal file
265
simulators/gem5/src/dev/mc146818.cc
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Andrew Schultz
|
||||
* Miguel Serrano
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/time.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/MC146818.hh"
|
||||
#include "dev/mc146818.hh"
|
||||
#include "dev/rtcreg.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static uint8_t
|
||||
bcdize(uint8_t val)
|
||||
{
|
||||
uint8_t result;
|
||||
result = val % 10;
|
||||
result += (val / 10) << 4;
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
unbcdize(uint8_t val)
|
||||
{
|
||||
uint8_t result;
|
||||
result = val & 0xf;
|
||||
result += (val >> 4) * 10;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
MC146818::setTime(const struct tm time)
|
||||
{
|
||||
curTime = time;
|
||||
year = time.tm_year;
|
||||
// Unix is 0-11 for month, data seet says start at 1
|
||||
mon = time.tm_mon + 1;
|
||||
mday = time.tm_mday;
|
||||
hour = time.tm_hour;
|
||||
min = time.tm_min;
|
||||
sec = time.tm_sec;
|
||||
|
||||
// Datasheet says 1 is sunday
|
||||
wday = time.tm_wday + 1;
|
||||
|
||||
if (!(stat_regB & RTCB_BIN)) {
|
||||
// The datasheet says that the year field can be either BCD or
|
||||
// years since 1900. Linux seems to be happy with years since
|
||||
// 1900.
|
||||
year = bcdize(year % 100);
|
||||
mon = bcdize(mon);
|
||||
mday = bcdize(mday);
|
||||
hour = bcdize(hour);
|
||||
min = bcdize(min);
|
||||
sec = bcdize(sec);
|
||||
}
|
||||
}
|
||||
|
||||
MC146818::MC146818(EventManager *em, const string &n, const struct tm time,
|
||||
bool bcd, Tick frequency)
|
||||
: EventManager(em), _name(n), event(this, frequency), tickEvent(this)
|
||||
{
|
||||
memset(clock_data, 0, sizeof(clock_data));
|
||||
stat_regA = RTCA_32768HZ | RTCA_1024HZ;
|
||||
stat_regB = RTCB_PRDC_IE | RTCB_24HR;
|
||||
if (!bcd)
|
||||
stat_regB |= RTCB_BIN;
|
||||
|
||||
setTime(time);
|
||||
DPRINTFN("Real-time clock set to %s", asctime(&time));
|
||||
}
|
||||
|
||||
MC146818::~MC146818()
|
||||
{
|
||||
deschedule(tickEvent);
|
||||
deschedule(event);
|
||||
}
|
||||
|
||||
void
|
||||
MC146818::writeData(const uint8_t addr, const uint8_t data)
|
||||
{
|
||||
if (addr < RTC_STAT_REGA) {
|
||||
clock_data[addr] = data;
|
||||
curTime.tm_sec = unbcdize(sec);
|
||||
curTime.tm_min = unbcdize(min);
|
||||
curTime.tm_hour = unbcdize(hour);
|
||||
curTime.tm_mday = unbcdize(mday);
|
||||
curTime.tm_mon = unbcdize(mon) - 1;
|
||||
curTime.tm_year = ((unbcdize(year) + 50) % 100) + 1950;
|
||||
curTime.tm_wday = unbcdize(wday) - 1;
|
||||
} else {
|
||||
switch (addr) {
|
||||
case RTC_STAT_REGA:
|
||||
// The "update in progress" bit is read only.
|
||||
if ((data & ~RTCA_UIP) != (RTCA_32768HZ | RTCA_1024HZ))
|
||||
panic("Unimplemented RTC register A value write!\n");
|
||||
replaceBits(stat_regA, data, 6, 0);
|
||||
break;
|
||||
case RTC_STAT_REGB:
|
||||
if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != RTCB_24HR)
|
||||
panic("Write to RTC reg B bits that are not implemented!\n");
|
||||
|
||||
if (data & RTCB_PRDC_IE) {
|
||||
if (!event.scheduled())
|
||||
event.scheduleIntr();
|
||||
} else {
|
||||
if (event.scheduled())
|
||||
deschedule(event);
|
||||
}
|
||||
stat_regB = data;
|
||||
break;
|
||||
case RTC_STAT_REGC:
|
||||
case RTC_STAT_REGD:
|
||||
panic("RTC status registers C and D are not implemented.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
MC146818::readData(uint8_t addr)
|
||||
{
|
||||
if (addr < RTC_STAT_REGA)
|
||||
return clock_data[addr];
|
||||
else {
|
||||
switch (addr) {
|
||||
case RTC_STAT_REGA:
|
||||
// toggle UIP bit for linux
|
||||
stat_regA ^= RTCA_UIP;
|
||||
return stat_regA;
|
||||
break;
|
||||
case RTC_STAT_REGB:
|
||||
return stat_regB;
|
||||
break;
|
||||
case RTC_STAT_REGC:
|
||||
case RTC_STAT_REGD:
|
||||
return 0x00;
|
||||
break;
|
||||
default:
|
||||
panic("Shouldn't be here");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MC146818::tickClock()
|
||||
{
|
||||
if (stat_regB & RTCB_NO_UPDT)
|
||||
return;
|
||||
time_t calTime = mkutctime(&curTime);
|
||||
calTime++;
|
||||
setTime(*gmtime(&calTime));
|
||||
}
|
||||
|
||||
void
|
||||
MC146818::serialize(const string &base, ostream &os)
|
||||
{
|
||||
arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data));
|
||||
paramOut(os, base + ".stat_regA", stat_regA);
|
||||
paramOut(os, base + ".stat_regB", stat_regB);
|
||||
|
||||
//
|
||||
// save the timer tick and rtc clock tick values to correctly reschedule
|
||||
// them during unserialize
|
||||
//
|
||||
Tick rtcTimerInterruptTickOffset = event.when() - curTick();
|
||||
SERIALIZE_SCALAR(rtcTimerInterruptTickOffset);
|
||||
Tick rtcClockTickOffset = tickEvent.when() - curTick();
|
||||
SERIALIZE_SCALAR(rtcClockTickOffset);
|
||||
}
|
||||
|
||||
void
|
||||
MC146818::unserialize(const string &base, Checkpoint *cp,
|
||||
const string §ion)
|
||||
{
|
||||
arrayParamIn(cp, section, base + ".clock_data", clock_data,
|
||||
sizeof(clock_data));
|
||||
paramIn(cp, section, base + ".stat_regA", stat_regA);
|
||||
paramIn(cp, section, base + ".stat_regB", stat_regB);
|
||||
|
||||
//
|
||||
// properly schedule the timer and rtc clock events
|
||||
//
|
||||
Tick rtcTimerInterruptTickOffset;
|
||||
UNSERIALIZE_SCALAR(rtcTimerInterruptTickOffset);
|
||||
reschedule(event, curTick() + rtcTimerInterruptTickOffset);
|
||||
Tick rtcClockTickOffset;
|
||||
UNSERIALIZE_SCALAR(rtcClockTickOffset);
|
||||
reschedule(tickEvent, curTick() + rtcClockTickOffset);
|
||||
}
|
||||
|
||||
MC146818::RTCEvent::RTCEvent(MC146818 * _parent, Tick i)
|
||||
: parent(_parent), interval(i)
|
||||
{
|
||||
DPRINTF(MC146818, "RTC Event Initilizing\n");
|
||||
parent->schedule(this, curTick() + interval);
|
||||
}
|
||||
|
||||
void
|
||||
MC146818::RTCEvent::scheduleIntr()
|
||||
{
|
||||
parent->schedule(this, curTick() + interval);
|
||||
}
|
||||
|
||||
void
|
||||
MC146818::RTCEvent::process()
|
||||
{
|
||||
DPRINTF(MC146818, "RTC Timer Interrupt\n");
|
||||
parent->schedule(this, curTick() + interval);
|
||||
parent->handleEvent();
|
||||
}
|
||||
|
||||
const char *
|
||||
MC146818::RTCEvent::description() const
|
||||
{
|
||||
return "RTC interrupt";
|
||||
}
|
||||
|
||||
void
|
||||
MC146818::RTCTickEvent::process()
|
||||
{
|
||||
DPRINTF(MC146818, "RTC clock tick\n");
|
||||
parent->schedule(this, curTick() + SimClock::Int::s);
|
||||
parent->tickClock();
|
||||
}
|
||||
|
||||
const char *
|
||||
MC146818::RTCTickEvent::description() const
|
||||
{
|
||||
return "RTC clock tick";
|
||||
}
|
||||
152
simulators/gem5/src/dev/mc146818.hh
Normal file
152
simulators/gem5/src/dev/mc146818.hh
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Andrew Schultz
|
||||
* Miguel Serrano
|
||||
*/
|
||||
|
||||
#ifndef __DEV_MC146818_HH__
|
||||
#define __DEV_MC146818_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "sim/eventq.hh"
|
||||
|
||||
/** Real-Time Clock (MC146818) */
|
||||
class MC146818 : public EventManager
|
||||
{
|
||||
protected:
|
||||
virtual void handleEvent()
|
||||
{
|
||||
warn("No RTC event handler defined.\n");
|
||||
}
|
||||
|
||||
private:
|
||||
/** Event for RTC periodic interrupt */
|
||||
struct RTCEvent : public Event
|
||||
{
|
||||
MC146818 * parent;
|
||||
Tick interval;
|
||||
|
||||
RTCEvent(MC146818 * _parent, Tick i);
|
||||
|
||||
/** Schedule the RTC periodic interrupt */
|
||||
void scheduleIntr();
|
||||
|
||||
/** Event process to occur at interrupt*/
|
||||
virtual void process();
|
||||
|
||||
/** Event description */
|
||||
virtual const char *description() const;
|
||||
};
|
||||
|
||||
/** Event for RTC periodic interrupt */
|
||||
struct RTCTickEvent : public Event
|
||||
{
|
||||
MC146818 * parent;
|
||||
|
||||
RTCTickEvent(MC146818 * _parent) : parent(_parent)
|
||||
{
|
||||
parent->schedule(this, curTick() + SimClock::Int::s);
|
||||
}
|
||||
|
||||
/** Event process to occur at interrupt*/
|
||||
void process();
|
||||
|
||||
/** Event description */
|
||||
const char *description() const;
|
||||
};
|
||||
|
||||
private:
|
||||
std::string _name;
|
||||
const std::string &name() const { return _name; }
|
||||
|
||||
/** RTC periodic interrupt event */
|
||||
RTCEvent event;
|
||||
|
||||
/** RTC tick event */
|
||||
RTCTickEvent tickEvent;
|
||||
|
||||
/** Data for real-time clock function */
|
||||
union {
|
||||
uint8_t clock_data[10];
|
||||
|
||||
struct {
|
||||
uint8_t sec;
|
||||
uint8_t sec_alrm;
|
||||
uint8_t min;
|
||||
uint8_t min_alrm;
|
||||
uint8_t hour;
|
||||
uint8_t hour_alrm;
|
||||
uint8_t wday;
|
||||
uint8_t mday;
|
||||
uint8_t mon;
|
||||
uint8_t year;
|
||||
};
|
||||
};
|
||||
|
||||
struct tm curTime;
|
||||
|
||||
void setTime(const struct tm time);
|
||||
|
||||
/** RTC status register A */
|
||||
uint8_t stat_regA;
|
||||
|
||||
/** RTC status register B */
|
||||
uint8_t stat_regB;
|
||||
|
||||
public:
|
||||
MC146818(EventManager *em, const std::string &name, const struct tm time,
|
||||
bool bcd, Tick frequency);
|
||||
virtual ~MC146818();
|
||||
|
||||
/** RTC write data */
|
||||
void writeData(const uint8_t addr, const uint8_t data);
|
||||
|
||||
/** RTC read data */
|
||||
uint8_t readData(const uint8_t addr);
|
||||
|
||||
void tickClock();
|
||||
|
||||
/**
|
||||
* Serialize this object to the given output stream.
|
||||
* @param base The base name of the counter object.
|
||||
* @param os The stream to serialize to.
|
||||
*/
|
||||
void serialize(const std::string &base, std::ostream &os);
|
||||
|
||||
/**
|
||||
* Reconstruct the state of this object from a checkpoint.
|
||||
* @param base The base name of the counter object.
|
||||
* @param cp The checkpoint use.
|
||||
* @param section The section name of this object
|
||||
*/
|
||||
void unserialize(const std::string &base, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
};
|
||||
|
||||
#endif // __DEV_MC146818_HH__
|
||||
68
simulators/gem5/src/dev/mips/Malta.py
Executable file
68
simulators/gem5/src/dev/mips/Malta.py
Executable file
@ -0,0 +1,68 @@
|
||||
# Copyright (c) 2007 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: Korey Sewell
|
||||
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
|
||||
from BadDevice import BadDevice
|
||||
from Device import BasicPioDevice
|
||||
from Pci import PciConfigAll
|
||||
from Platform import Platform
|
||||
from Uart import Uart8250
|
||||
|
||||
class MaltaCChip(BasicPioDevice):
|
||||
type = 'MaltaCChip'
|
||||
malta = Param.Malta(Parent.any, "Malta")
|
||||
|
||||
class MaltaIO(BasicPioDevice):
|
||||
type = 'MaltaIO'
|
||||
time = Param.Time('01/01/2009',
|
||||
"System time to use (0 for actual time, default is 1/1/06)")
|
||||
year_is_bcd = Param.Bool(False,
|
||||
"The RTC should interpret the year as a BCD value")
|
||||
malta = Param.Malta(Parent.any, "Malta")
|
||||
frequency = Param.Frequency('1024Hz', "frequency of interrupts")
|
||||
|
||||
class MaltaPChip(BasicPioDevice):
|
||||
type = 'MaltaPChip'
|
||||
malta = Param.Malta(Parent.any, "Malta")
|
||||
|
||||
class Malta(Platform):
|
||||
type = 'Malta'
|
||||
system = Param.System(Parent.any, "system")
|
||||
cchip = MaltaCChip(pio_addr=0x801a0000000)
|
||||
io = MaltaIO(pio_addr=0x801fc000000)
|
||||
uart = Uart8250(pio_addr=0xBFD003F8)
|
||||
|
||||
# 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.
|
||||
def attachIO(self, bus):
|
||||
self.cchip.pio = bus.master
|
||||
self.io.pio = bus.master
|
||||
self.uart.pio = bus.master
|
||||
42
simulators/gem5/src/dev/mips/SConscript
Executable file
42
simulators/gem5/src/dev/mips/SConscript
Executable file
@ -0,0 +1,42 @@
|
||||
# -*- mode:python -*-
|
||||
|
||||
# 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: Steve Reinhardt
|
||||
# Gabe Black
|
||||
|
||||
Import('*')
|
||||
|
||||
if env['TARGET_ISA'] == 'mips':
|
||||
SimObject('Malta.py')
|
||||
|
||||
DebugFlag('Malta')
|
||||
|
||||
Source('malta.cc')
|
||||
Source('malta_cchip.cc')
|
||||
Source('malta_io.cc')
|
||||
Source('malta_pchip.cc')
|
||||
84
simulators/gem5/src/dev/mips/access.h
Executable file
84
simulators/gem5/src/dev/mips/access.h
Executable file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 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: Nathan Binkert
|
||||
*/
|
||||
|
||||
#ifndef __MIPS_ACCESS_H__
|
||||
#define __MIPS_ACCESS_H__
|
||||
|
||||
/** @file
|
||||
* System Console Memory Mapped Register Definition
|
||||
*/
|
||||
|
||||
#define MIPS_ACCESS_VERSION (1305)
|
||||
#define CONSOLE_START_ADDRESS 0xBFD00F00
|
||||
#define REG_OFFSET 1
|
||||
#define UART8250_BASE 0xBFD003F8
|
||||
#define UART8250_END 7*REG_OFFSET
|
||||
#ifdef CONSOLE
|
||||
typedef unsigned uint32_t;
|
||||
typedef unsigned long uint64_t;
|
||||
#endif
|
||||
|
||||
// This structure hacked up from simos
|
||||
struct MipsAccess
|
||||
{
|
||||
uint32_t inputChar; // 00: Placeholder for input
|
||||
uint32_t last_offset; // 04: must be first field
|
||||
uint32_t version; // 08:
|
||||
uint32_t numCPUs; // 0C:
|
||||
uint32_t intrClockFrequency; // 10: Hz
|
||||
|
||||
// Loaded kernel
|
||||
uint32_t kernStart; // 14:
|
||||
uint32_t kernEnd; // 18:
|
||||
uint32_t entryPoint; // 1c:
|
||||
|
||||
// console simple output stuff
|
||||
uint32_t outputChar; // 20: Placeholder for output
|
||||
|
||||
// console disk stuff
|
||||
uint32_t diskUnit; // 24:
|
||||
uint32_t diskCount; // 28:
|
||||
uint32_t diskPAddr; // 2c:
|
||||
uint32_t diskBlock; // 30:
|
||||
uint32_t diskOperation; // 34:
|
||||
|
||||
// MP boot
|
||||
uint32_t cpuStack[64]; // 70:
|
||||
|
||||
/* XXX There appears to be a problem in accessing
|
||||
* unit64_t in the console.c file. They are treated
|
||||
* like uint32_int and result in the wrong address for
|
||||
* everything below. This problem should be investigated.
|
||||
*/
|
||||
uint64_t cpuClock; // 38: MHz
|
||||
uint64_t mem_size; // 40:
|
||||
};
|
||||
|
||||
#endif // __MIPS_ACCESS_H__
|
||||
BIN
simulators/gem5/src/dev/mips/console
Normal file
BIN
simulators/gem5/src/dev/mips/console
Normal file
Binary file not shown.
109
simulators/gem5/src/dev/mips/malta.cc
Executable file
109
simulators/gem5/src/dev/mips/malta.cc
Executable file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Rick Strong
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Implementation of Malta platform.
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "config/the_isa.hh"
|
||||
#include "cpu/intr_control.hh"
|
||||
#include "debug/Malta.hh"
|
||||
#include "dev/mips/malta.hh"
|
||||
#include "dev/mips/malta_cchip.hh"
|
||||
#include "dev/mips/malta_io.hh"
|
||||
#include "dev/mips/malta_pchip.hh"
|
||||
#include "dev/terminal.hh"
|
||||
#include "params/Malta.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
using namespace std;
|
||||
using namespace TheISA;
|
||||
|
||||
Malta::Malta(const Params *p)
|
||||
: Platform(p), system(p->system)
|
||||
{
|
||||
for (int i = 0; i < Malta::Max_CPUs; i++)
|
||||
intr_sum_type[i] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Malta::postConsoleInt()
|
||||
{
|
||||
//see {Linux-src}/arch/mips/mips-boards/sim/sim_setup.c
|
||||
io->postIntr(0x10/*HW4*/);
|
||||
}
|
||||
|
||||
void
|
||||
Malta::clearConsoleInt()
|
||||
{
|
||||
//FIXME: implement clearConsoleInt()
|
||||
io->clearIntr(0x10/*HW4*/);
|
||||
}
|
||||
|
||||
void
|
||||
Malta::postPciInt(int line)
|
||||
{
|
||||
panic("Malta::postPciInt() has not been implemented.");
|
||||
}
|
||||
|
||||
void
|
||||
Malta::clearPciInt(int line)
|
||||
{
|
||||
panic("Malta::clearPciInt() has not been implemented.");
|
||||
}
|
||||
|
||||
Addr
|
||||
Malta::pciToDma(Addr pciAddr) const
|
||||
{
|
||||
panic("Malta::pciToDma() has not been implemented.");
|
||||
}
|
||||
|
||||
void
|
||||
Malta::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_ARRAY(intr_sum_type, Malta::Max_CPUs);
|
||||
}
|
||||
|
||||
void
|
||||
Malta::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_ARRAY(intr_sum_type, Malta::Max_CPUs);
|
||||
}
|
||||
|
||||
Malta *
|
||||
MaltaParams::create()
|
||||
{
|
||||
return new Malta(this);
|
||||
}
|
||||
152
simulators/gem5/src/dev/mips/malta.hh
Executable file
152
simulators/gem5/src/dev/mips/malta.hh
Executable file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 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
|
||||
* Rick Strong
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Declaration of top level class for the Malta chipset. This class just
|
||||
* retains pointers to all its children so the children can communicate.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_MALTA_HH__
|
||||
#define __DEV_MALTA_HH__
|
||||
|
||||
#include "dev/platform.hh"
|
||||
#include "params/Malta.hh"
|
||||
|
||||
class IdeController;
|
||||
class MaltaCChip;
|
||||
class MaltaPChip;
|
||||
class MaltaIO;
|
||||
class System;
|
||||
|
||||
/**
|
||||
* Top level class for Malta Chipset emulation.
|
||||
* This structure just contains pointers to all the
|
||||
* children so the children can commnicate to do the
|
||||
* read work
|
||||
*/
|
||||
|
||||
class Malta : public Platform
|
||||
{
|
||||
public:
|
||||
/** Max number of CPUs in a Malta */
|
||||
static const int Max_CPUs = 64;
|
||||
|
||||
/** Pointer to the system */
|
||||
System *system;
|
||||
|
||||
/** Pointer to the MaltaIO device which has the RTC */
|
||||
MaltaIO *io;
|
||||
|
||||
/** Pointer to the Malta CChip.
|
||||
* The chip contains some configuration information and
|
||||
* all the interrupt mask and status registers
|
||||
*/
|
||||
MaltaCChip *cchip;
|
||||
|
||||
/** Pointer to the Malta PChip.
|
||||
* The pchip is the interface to the PCI bus, in our case
|
||||
* it does not have to do much.
|
||||
*/
|
||||
MaltaPChip *pchip;
|
||||
|
||||
int intr_sum_type[Malta::Max_CPUs];
|
||||
int ipi_pending[Malta::Max_CPUs];
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor for the Malta Class.
|
||||
* @param name name of the object
|
||||
* @param s system the object belongs to
|
||||
* @param intctrl pointer to the interrupt controller
|
||||
*/
|
||||
typedef MaltaParams Params;
|
||||
Malta(const Params *p);
|
||||
|
||||
/**
|
||||
* Cause the cpu to post a serial interrupt to the CPU.
|
||||
*/
|
||||
virtual void postConsoleInt();
|
||||
|
||||
/**
|
||||
* Clear a posted CPU interrupt (id=55)
|
||||
*/
|
||||
virtual void clearConsoleInt();
|
||||
|
||||
/**
|
||||
* Cause the chipset to post a cpi interrupt to the CPU.
|
||||
*/
|
||||
virtual void postPciInt(int line);
|
||||
|
||||
/**
|
||||
* Clear a posted PCI->CPU interrupt
|
||||
*/
|
||||
virtual void clearPciInt(int line);
|
||||
|
||||
|
||||
virtual Addr pciToDma(Addr pciAddr) const;
|
||||
|
||||
Addr
|
||||
calcPciConfigAddr(int bus, int dev, int func)
|
||||
{
|
||||
panic("Need implementation\n");
|
||||
M5_DUMMY_RETURN
|
||||
}
|
||||
|
||||
Addr
|
||||
calcPciIOAddr(Addr addr)
|
||||
{
|
||||
panic("Need implementation\n");
|
||||
M5_DUMMY_RETURN
|
||||
}
|
||||
|
||||
Addr
|
||||
calcPciMemAddr(Addr addr)
|
||||
{
|
||||
panic("Need implementation\n");
|
||||
M5_DUMMY_RETURN
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize this object to the given output stream.
|
||||
* @param os The stream to serialize to.
|
||||
*/
|
||||
virtual void serialize(std::ostream &os);
|
||||
|
||||
/**
|
||||
* Reconstruct the state of this object from a checkpoint.
|
||||
* @param cp The checkpoint use.
|
||||
* @param section The section name of this object
|
||||
*/
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
#endif // __DEV_MALTA_HH__
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user