diff options
author | Andreas Hansson <andreas.hansson@arm.com> | 2012-02-13 06:43:09 -0500 |
---|---|---|
committer | Andreas Hansson <andreas.hansson@arm.com> | 2012-02-13 06:43:09 -0500 |
commit | 5a9a743cfc4517f93e5c94533efa767b92272c59 (patch) | |
tree | f3dbc078a51e5759b26b1a5f16263ddb1cf55a7b /src | |
parent | 8cb4a2208d568eb86ad3f6c6bb250bcbe2952302 (diff) | |
download | gem5-5a9a743cfc4517f93e5c94533efa767b92272c59.tar.xz |
MEM: Introduce the master/slave port roles in the Python classes
This patch classifies all ports in Python as either Master or Slave
and enforces a binding of master to slave. Conceptually, a master (such
as a CPU or DMA port) issues requests, and receives responses, and
conversely, a slave (such as a memory or a PIO device) receives
requests and sends back responses. Currently there is no
differentiation between coherent and non-coherent masters and slaves.
The classification as master/slave also involves splitting the dual
role port of the bus into a master and slave port and updating all the
system assembly scripts to use the appropriate port. Similarly, the
interrupt devices have to have their int_port split into a master and
slave port. The intdev and its children have minimal changes to
facilitate the extra port.
Note that this patch does not enforce any port typing in the C++
world, it merely ensures that the Python objects have a notion of the
port roles and are connected in an appropriate manner. This check is
carried when two ports are connected, e.g. bus.master =
memory.port. The following patches will make use of the
classifications and specialise the C++ ports into masters and slaves.
Diffstat (limited to 'src')
29 files changed, 321 insertions, 201 deletions
diff --git a/src/arch/arm/ArmTLB.py b/src/arch/arm/ArmTLB.py index fc6f51d84..8599fa75f 100644 --- a/src/arch/arm/ArmTLB.py +++ b/src/arch/arm/ArmTLB.py @@ -45,7 +45,7 @@ from MemObject import MemObject class ArmTableWalker(MemObject): type = 'ArmTableWalker' cxx_class = 'ArmISA::TableWalker' - port = Port("Port for TableWalker to do walk the translation with") + port = MasterPort("Port for TableWalker to do walk the translation with") sys = Param.System(Parent.any, "system object parameter") min_backoff = Param.Tick(0, "Minimum backoff delay after failed send") max_backoff = Param.Tick(100000, "Minimum backoff delay after failed send") diff --git a/src/arch/x86/X86LocalApic.py b/src/arch/x86/X86LocalApic.py index 2f53c4e24..283d94ba7 100644 --- a/src/arch/x86/X86LocalApic.py +++ b/src/arch/x86/X86LocalApic.py @@ -1,3 +1,15 @@ +# 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. # @@ -35,6 +47,7 @@ class X86LocalApic(BasicPioDevice): type = 'X86LocalApic' cxx_class = 'X86ISA::Interrupts' pio_latency = Param.Latency('1ns', 'Programmed IO latency in simticks') - int_port = Port("Port for sending and receiving interrupt messages") + int_master = MasterPort("Port for sending interrupt messages") + int_slave = SlavePort("Port for receiving interrupt messages") int_latency = Param.Latency('1ns', \ "Latency for an interrupt to propagate through this device.") diff --git a/src/arch/x86/X86TLB.py b/src/arch/x86/X86TLB.py index 7f2fcd358..334d2a0cf 100644 --- a/src/arch/x86/X86TLB.py +++ b/src/arch/x86/X86TLB.py @@ -44,7 +44,7 @@ from MemObject import MemObject class X86PagetableWalker(MemObject): type = 'X86PagetableWalker' cxx_class = 'X86ISA::Walker' - port = Port("Port for the hardware table walker") + port = MasterPort("Port for the hardware table walker") system = Param.System(Parent.any, "system object") class X86TLB(BaseTLB): diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index 8567b30f0..13ad2069b 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -1,4 +1,16 @@ /* + * 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) 2007 The Hewlett-Packard Development Company * All rights reserved. * @@ -35,6 +47,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Gabe Black + * Andreas Hansson */ #ifndef __ARCH_X86_INTERRUPTS_HH__ @@ -225,8 +238,15 @@ class Interrupts : public BasicPioDevice, IntDev Port *getPort(const std::string &if_name, int idx = -1) { - if (if_name == "int_port") + // a bit of an odd one since there is now two ports in the + // Python class we also need two ports even if they are + // identical + if (if_name == "int_master") { return intPort; + } else if (if_name == "int_slave") { + // memory leak...but will be removed in the next patch + return new IntPort(name() + ".int_slave", this, this, latency); + } return BasicPioDevice::getPort(if_name, idx); } diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index fda0a3bc8..0bb2090ad 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -1,3 +1,15 @@ +# 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) 2005-2008 The Regents of The University of Michigan # Copyright (c) 2011 Regents of the University of California # All rights reserved. @@ -27,6 +39,7 @@ # # Authors: Nathan Binkert # Rick Strong +# Andreas Hansson import sys @@ -138,24 +151,28 @@ class BaseCPU(MemObject): tracer = Param.InstTracer(default_tracer, "Instruction tracer") - icache_port = Port("Instruction Port") - dcache_port = Port("Data Port") + icache_port = MasterPort("Instruction Port") + dcache_port = MasterPort("Data Port") _cached_ports = ['icache_port', 'dcache_port'] if buildEnv['TARGET_ISA'] in ['x86', 'arm']: _cached_ports += ["itb.walker.port", "dtb.walker.port"] - _uncached_ports = [] + _uncached_slave_ports = [] + _uncached_master_ports = [] if buildEnv['TARGET_ISA'] == 'x86': - _uncached_ports = ["interrupts.pio", "interrupts.int_port"] + _uncached_slave_ports += ["interrupts.pio", "interrupts.int_slave"] + _uncached_master_ports += ["interrupts.int_master"] def connectCachedPorts(self, bus): for p in self._cached_ports: - exec('self.%s = bus.port' % p) + exec('self.%s = bus.slave' % p) def connectUncachedPorts(self, bus): - for p in self._uncached_ports: - exec('self.%s = bus.port' % p) + for p in self._uncached_slave_ports: + exec('self.%s = bus.master' % p) + for p in self._uncached_master_ports: + exec('self.%s = bus.slave' % p) def connectAllPorts(self, cached_bus, uncached_bus = None): self.connectCachedPorts(cached_bus) @@ -190,5 +207,5 @@ class BaseCPU(MemObject): self.toL2Bus = Bus() self.connectCachedPorts(self.toL2Bus) self.l2cache = l2c - self.l2cache.cpu_side = self.toL2Bus.port + self.toL2Bus.master = self.l2cache.cpu_side self._cached_ports = ['l2cache.mem_side'] diff --git a/src/cpu/simple/AtomicSimpleCPU.py b/src/cpu/simple/AtomicSimpleCPU.py index 93cd02ba7..1199f35e1 100644 --- a/src/cpu/simple/AtomicSimpleCPU.py +++ b/src/cpu/simple/AtomicSimpleCPU.py @@ -34,4 +34,4 @@ class AtomicSimpleCPU(BaseSimpleCPU): width = Param.Int(1, "CPU width") simulate_data_stalls = Param.Bool(False, "Simulate dcache stall cycles") simulate_inst_stalls = Param.Bool(False, "Simulate icache stall cycles") - physmem_port = Port("Physical Memory Port") + physmem_port = MasterPort("Physical Memory Port") diff --git a/src/cpu/testers/directedtest/RubyDirectedTester.py b/src/cpu/testers/directedtest/RubyDirectedTester.py index ccadc5b36..bf3eace08 100644 --- a/src/cpu/testers/directedtest/RubyDirectedTester.py +++ b/src/cpu/testers/directedtest/RubyDirectedTester.py @@ -48,6 +48,6 @@ class InvalidateGenerator(DirectedGenerator): class RubyDirectedTester(MemObject): type = 'RubyDirectedTester' - cpuPort = VectorPort("the cpu ports") + cpuPort = VectorMasterPort("the cpu ports") requests_to_complete = Param.Int("checks to complete") generator = Param.DirectedGenerator("the request generator") diff --git a/src/cpu/testers/memtest/MemTest.py b/src/cpu/testers/memtest/MemTest.py index 6a3568379..1b4d6767c 100644 --- a/src/cpu/testers/memtest/MemTest.py +++ b/src/cpu/testers/memtest/MemTest.py @@ -48,8 +48,9 @@ class MemTest(MemObject): "progress report interval (in accesses)") trace_addr = Param.Addr(0, "address to trace") - test = Port("Port to the memory system to test") - functional = Port("Port to the functional memory used for verification") + test = MasterPort("Port to the memory system to test") + functional = MasterPort("Port to the functional memory " \ + "used for verification") suppress_func_warnings = Param.Bool(False, "suppress warnings when functional accesses fail.\n") sys = Param.System(Parent.any, "System Parameter") diff --git a/src/cpu/testers/networktest/NetworkTest.py b/src/cpu/testers/networktest/NetworkTest.py index b2eda9aa2..7d6ed576b 100644 --- a/src/cpu/testers/networktest/NetworkTest.py +++ b/src/cpu/testers/networktest/NetworkTest.py @@ -41,5 +41,5 @@ class NetworkTest(MemObject): traffic_type = Param.Counter(0, "Traffic type: uniform random, tornado, bit complement") inj_rate = Param.Float(0.1, "Packet injection rate") precision = Param.Int(3, "Number of digits of precision after decimal point") - test = Port("Port to the memory system to test") + test = MasterPort("Port to the memory system to test") system = Param.System(Parent.any, "System we belong to") diff --git a/src/cpu/testers/rubytest/RubyTester.py b/src/cpu/testers/rubytest/RubyTester.py index fc0a60e11..6518862e9 100644 --- a/src/cpu/testers/rubytest/RubyTester.py +++ b/src/cpu/testers/rubytest/RubyTester.py @@ -32,7 +32,7 @@ from m5.proxy import * class RubyTester(MemObject): type = 'RubyTester' - cpuPort = VectorPort("the cpu ports") + cpuPort = VectorMasterPort("the cpu ports") checks_to_complete = Param.Int(100, "checks to complete") deadlock_threshold = Param.Int(50000, "how often to check for deadlock") wakeup_frequency = Param.Int(10, "number of cycles between wakeups") diff --git a/src/dev/Device.py b/src/dev/Device.py index c32946277..96c95ebc9 100644 --- a/src/dev/Device.py +++ b/src/dev/Device.py @@ -33,7 +33,7 @@ from MemObject import MemObject class PioDevice(MemObject): type = 'PioDevice' abstract = True - pio = Port("Programmed I/O port") + pio = SlavePort("Programmed I/O port") system = Param.System(Parent.any, "System this device is part of") class BasicPioDevice(PioDevice): @@ -45,7 +45,7 @@ class BasicPioDevice(PioDevice): class DmaDevice(PioDevice): type = 'DmaDevice' abstract = True - dma = Port("DMA port") + 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', diff --git a/src/dev/Ethernet.py b/src/dev/Ethernet.py index 539e4ea9b..91d4e230e 100644 --- a/src/dev/Ethernet.py +++ b/src/dev/Ethernet.py @@ -37,8 +37,8 @@ class EtherObject(SimObject): class EtherLink(EtherObject): type = 'EtherLink' - int0 = Port("interface 0") - int1 = Port("interface 1") + 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") @@ -64,7 +64,7 @@ class EtherDump(SimObject): class EtherDevice(PciDevice): type = 'EtherDevice' abstract = True - interface = Port("Ethernet Interface") + interface = MasterPort("Ethernet Interface") class IGbE(EtherDevice): # Base class for two IGbE adapters listed above diff --git a/src/dev/Pci.py b/src/dev/Pci.py index 95cb3916f..c866f9386 100644 --- a/src/dev/Pci.py +++ b/src/dev/Pci.py @@ -43,7 +43,7 @@ class PciDevice(DmaDevice): type = 'PciDevice' abstract = True platform = Param.Platform(Parent.any, "Platform this device is part of.") - config = Port("PCI configuration space port") + 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") diff --git a/src/dev/alpha/Tsunami.py b/src/dev/alpha/Tsunami.py index e6a899604..9a3ec0593 100644 --- a/src/dev/alpha/Tsunami.py +++ b/src/dev/alpha/Tsunami.py @@ -93,30 +93,30 @@ class Tsunami(Platform): # earlier, since the bus object itself is typically defined at the # System level. def attachIO(self, bus): - self.cchip.pio = bus.port - self.pchip.pio = bus.port + 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.port - self.fake_uart1.pio = bus.port - self.fake_uart2.pio = bus.port - self.fake_uart3.pio = bus.port - self.fake_uart4.pio = bus.port - self.fake_ppc.pio = bus.port - self.fake_OROM.pio = bus.port - self.fake_pnp_addr.pio = bus.port - self.fake_pnp_write.pio = bus.port - self.fake_pnp_read0.pio = bus.port - self.fake_pnp_read1.pio = bus.port - self.fake_pnp_read2.pio = bus.port - self.fake_pnp_read3.pio = bus.port - self.fake_pnp_read4.pio = bus.port - self.fake_pnp_read5.pio = bus.port - self.fake_pnp_read6.pio = bus.port - self.fake_pnp_read7.pio = bus.port - self.fake_ata0.pio = bus.port - self.fake_ata1.pio = bus.port - self.fb.pio = bus.port - self.io.pio = bus.port - self.uart.pio = bus.port - self.backdoor.pio = bus.port + 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 diff --git a/src/dev/arm/RealView.py b/src/dev/arm/RealView.py index 3da47399e..e42bc4b94 100644 --- a/src/dev/arm/RealView.py +++ b/src/dev/arm/RealView.py @@ -181,10 +181,10 @@ class RealViewPBX(RealView): # 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.port - self.l2x0_fake.pio = bus.port - self.a9scu.pio = bus.port - self.local_cpu_timer.pio = bus.port + 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, @@ -195,33 +195,33 @@ class RealViewPBX(RealView): # earlier, since the bus object itself is typically defined at the # System level. def attachIO(self, bus): - self.uart.pio = bus.port - self.realview_io.pio = bus.port - self.timer0.pio = bus.port - self.timer1.pio = bus.port - self.clcd.pio = bus.port - self.clcd.dma = bus.port - self.kmi0.pio = bus.port - self.kmi1.pio = bus.port - self.cf_ctrl.pio = bus.port - self.cf_ctrl.config = bus.port - self.cf_ctrl.dma = bus.port - self.dmac_fake.pio = bus.port - self.uart1_fake.pio = bus.port - self.uart2_fake.pio = bus.port - self.uart3_fake.pio = bus.port - self.smc_fake.pio = bus.port - self.sp810_fake.pio = bus.port - self.watchdog_fake.pio = bus.port - self.gpio0_fake.pio = bus.port - self.gpio1_fake.pio = bus.port - self.gpio2_fake.pio = bus.port - self.ssp_fake.pio = bus.port - self.sci_fake.pio = bus.port - self.aaci_fake.pio = bus.port - self.mmc_fake.pio = bus.port - self.rtc_fake.pio = bus.port - self.flash_fake.pio = bus.port + 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_fake.pio = bus.master + self.flash_fake.pio = bus.master # Reference for memory map and interrupt number # RealView Emulation Baseboard User Guide (ARM DUI 0143B) @@ -261,8 +261,8 @@ class RealViewEB(RealView): # 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.port - self.l2x0_fake.pio = bus.port + 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, @@ -273,31 +273,31 @@ class RealViewEB(RealView): # earlier, since the bus object itself is typically defined at the # System level. def attachIO(self, bus): - self.uart.pio = bus.port - self.realview_io.pio = bus.port - self.timer0.pio = bus.port - self.timer1.pio = bus.port - self.clcd.pio = bus.port - self.clcd.dma = bus.port - self.kmi0.pio = bus.port - self.kmi1.pio = bus.port - self.dmac_fake.pio = bus.port - self.uart1_fake.pio = bus.port - self.uart2_fake.pio = bus.port - self.uart3_fake.pio = bus.port - self.smc_fake.pio = bus.port - self.sp810_fake.pio = bus.port - self.watchdog_fake.pio = bus.port - self.gpio0_fake.pio = bus.port - self.gpio1_fake.pio = bus.port - self.gpio2_fake.pio = bus.port - self.ssp_fake.pio = bus.port - self.sci_fake.pio = bus.port - self.aaci_fake.pio = bus.port - self.mmc_fake.pio = bus.port - self.rtc_fake.pio = bus.port - self.flash_fake.pio = bus.port - self.smcreg_fake.pio = bus.port + 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_ELT(RealView): pci_cfg_base = 0xD0000000 @@ -349,9 +349,9 @@ class VExpress_ELT(RealView): # 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.port - self.a9scu.pio = bus.port - self.local_cpu_timer.pio = bus.port + self.gic.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, a9scu) bridge.ranges = [AddrRange(self.pci_cfg_base, self.a9scu.pio_addr - 1), @@ -361,44 +361,44 @@ class VExpress_ELT(RealView): # earlier, since the bus object itself is typically defined at the # System level. def attachIO(self, bus): - self.elba_uart.pio = bus.port - self.uart.pio = bus.port - self.realview_io.pio = bus.port - self.v2m_timer0.pio = bus.port - self.v2m_timer1.pio = bus.port - self.elba_timer0.pio = bus.port - self.elba_timer1.pio = bus.port - self.clcd.pio = bus.port - self.clcd.dma = bus.port - self.kmi0.pio = bus.port - self.kmi1.pio = bus.port - self.elba_kmi0.pio = bus.port - self.elba_kmi1.pio = bus.port - self.cf_ctrl.pio = bus.port - self.cf_ctrl.config = bus.port + self.elba_uart.pio = bus.master + self.uart.pio = bus.master + self.realview_io.pio = bus.master + self.v2m_timer0.pio = bus.master + self.v2m_timer1.pio = bus.master + self.elba_timer0.pio = bus.master + self.elba_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.elba_kmi0.pio = bus.master + self.elba_kmi1.pio = bus.master + self.cf_ctrl.pio = bus.master + self.cf_ctrl.config = bus.master self.cf_ctrl.dma = bus.port - self.ide.pio = bus.port - self.ide.config = bus.port - self.ide.dma = bus.port - self.ethernet.pio = bus.port - self.ethernet.config = bus.port - self.ethernet.dma = bus.port + 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 bus.use_default_range = True - self.l2x0_fake.pio = bus.port - self.dmac_fake.pio = bus.port - self.uart1_fake.pio = bus.port - self.uart2_fake.pio = bus.port - self.uart3_fake.pio = bus.port - self.smc_fake.pio = bus.port - self.sp810_fake.pio = bus.port - self.watchdog_fake.pio = bus.port - self.aaci_fake.pio = bus.port - self.elba_aaci_fake.pio = bus.port - self.mmc_fake.pio = bus.port - self.rtc_fake.pio = bus.port - self.spsc_fake.pio = bus.port - self.lan_fake.pio = bus.port - self.usb_fake.pio = bus.port + self.l2x0_fake.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.aaci_fake.pio = bus.master + self.elba_aaci_fake.pio = bus.master + self.mmc_fake.pio = bus.master + self.rtc_fake.pio = bus.master + self.spsc_fake.pio = bus.master + self.lan_fake.pio = bus.master + self.usb_fake.pio = bus.master diff --git a/src/dev/x86/I82094AA.py b/src/dev/x86/I82094AA.py index d4ab2cb17..09923f6c2 100644 --- a/src/dev/x86/I82094AA.py +++ b/src/dev/x86/I82094AA.py @@ -37,7 +37,7 @@ class I82094AA(BasicPioDevice): apic_id = Param.Int(1, 'APIC id for this IO APIC') pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") pio_addr = Param.Addr("Device address") - int_port = Port("Port for sending and receiving interrupt messages") + int_master = MasterPort("Port for sending interrupt messages") int_latency = Param.Latency('1ns', \ "Latency for an interrupt to propagate through this device.") external_int_pic = Param.I8259(NULL, "External PIC, if any") diff --git a/src/dev/x86/Pc.py b/src/dev/x86/Pc.py index bb8c91ac6..5b7d0864e 100644 --- a/src/dev/x86/Pc.py +++ b/src/dev/x86/Pc.py @@ -71,12 +71,12 @@ class Pc(Platform): def attachIO(self, bus): self.south_bridge.attachIO(bus) - self.i_dont_exist.pio = bus.port - self.behind_pci.pio = bus.port - self.com_1.pio = bus.port - self.fake_com_2.pio = bus.port - self.fake_com_3.pio = bus.port - self.fake_com_4.pio = bus.port - self.fake_floppy.pio = bus.port + self.i_dont_exist.pio = bus.master + self.behind_pci.pio = bus.master + self.com_1.pio = bus.master + self.fake_com_2.pio = bus.master + self.fake_com_3.pio = bus.master + self.fake_com_4.pio = bus.master + self.fake_floppy.pio = bus.master self.pciconfig.pio = bus.default bus.use_default_range = True diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index baff35e0b..9f7070e96 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -102,15 +102,15 @@ class SouthBridge(SimObject): self.speaker.i8254 = self.pit self.io_apic.external_int_pic = self.pic1 # Connect to the bus - self.cmos.pio = bus.port - self.dma1.pio = bus.port - self.ide.pio = bus.port - self.ide.config = bus.port - self.ide.dma = bus.port - self.keyboard.pio = bus.port - self.pic1.pio = bus.port - self.pic2.pio = bus.port - self.pit.pio = bus.port - self.speaker.pio = bus.port - self.io_apic.pio = bus.port - self.io_apic.int_port = bus.port + self.cmos.pio = bus.master + self.dma1.pio = bus.master + self.ide.pio = bus.master + self.ide.config = bus.master + self.ide.dma = bus.slave + self.keyboard.pio = bus.master + self.pic1.pio = bus.master + self.pic2.pio = bus.master + self.pit.pio = bus.master + self.speaker.pio = bus.master + self.io_apic.pio = bus.master + self.io_apic.int_master = bus.slave diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh index dfef059c3..60ef27012 100644 --- a/src/dev/x86/i82094aa.hh +++ b/src/dev/x86/i82094aa.hh @@ -123,7 +123,7 @@ class I82094AA : public PioDevice, public IntDev Port *getPort(const std::string &if_name, int idx = -1) { - if (if_name == "int_port") + if (if_name == "int_master") return intPort; return PioDevice::getPort(if_name, idx); } diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh index 9713d042b..05b4d12a1 100644 --- a/src/dev/x86/intdev.hh +++ b/src/dev/x86/intdev.hh @@ -90,7 +90,7 @@ class IntDev IntDev(MemObject * parent, Tick latency = 0) { if (parent != NULL) { - intPort = new IntPort(parent->name() + ".int_port", + intPort = new IntPort(parent->name() + ".int_master", parent, this, latency); } else { intPort = NULL; diff --git a/src/mem/Bridge.py b/src/mem/Bridge.py index 38b344613..ea8684e1b 100644 --- a/src/mem/Bridge.py +++ b/src/mem/Bridge.py @@ -31,8 +31,8 @@ from MemObject import MemObject class Bridge(MemObject): type = 'Bridge' - slave = Port('Slave port') - master = Port('Master port') + slave = SlavePort('Slave port') + master = MasterPort('Master port') req_size = Param.Int(16, "The number of requests to buffer") resp_size = Param.Int(16, "The number of requests to buffer") delay = Param.Latency('0ns', "The latency of this bridge") diff --git a/src/mem/Bus.py b/src/mem/Bus.py index fda91742f..91043da80 100644 --- a/src/mem/Bus.py +++ b/src/mem/Bus.py @@ -33,13 +33,14 @@ from MemObject import MemObject class Bus(MemObject): type = 'Bus' - port = VectorPort("vector port for connecting devices") + slave = VectorSlavePort("vector port for connecting masters") + master = VectorMasterPort("vector port for connecting slaves") bus_id = Param.Int(0, "blah") clock = Param.Clock("1GHz", "bus clock speed") header_cycles = Param.Int(1, "cycles of overhead per transaction") width = Param.Int(64, "bus width (bytes)") block_size = Param.Int(64, "The default block size if one isn't set by a device attached to the bus.") - default = \ - Port("Default port for requests that aren't handled by a device.") + default = MasterPort("Default port for requests that aren't handled " \ + "by a device.") use_default_range = \ Param.Bool(False, "Query default port device for legal range.") diff --git a/src/mem/PhysicalMemory.py b/src/mem/PhysicalMemory.py index 95cc73daa..c5f80b4c9 100644 --- a/src/mem/PhysicalMemory.py +++ b/src/mem/PhysicalMemory.py @@ -32,7 +32,7 @@ from MemObject import * class PhysicalMemory(MemObject): type = 'PhysicalMemory' - port = VectorPort("the access port") + port = VectorSlavePort("the access port") range = Param.AddrRange(AddrRange('128MB'), "Device Address") file = Param.String('', "memory mapped file") latency = Param.Latency('30ns', "latency of an access") diff --git a/src/mem/cache/BaseCache.py b/src/mem/cache/BaseCache.py index 4389eb356..adc48a461 100644 --- a/src/mem/cache/BaseCache.py +++ b/src/mem/cache/BaseCache.py @@ -58,7 +58,7 @@ class BaseCache(MemObject): prefetch_on_access = Param.Bool(False, "notify the hardware prefetcher on every access (not just misses)") prefetcher = Param.BasePrefetcher(NULL,"Prefetcher attached to cache") - cpu_side = Port("Port on side closer to CPU") - mem_side = Port("Port on side closer to MEM") + cpu_side = SlavePort("Port on side closer to CPU") + mem_side = MasterPort("Port on side closer to MEM") addr_range = Param.AddrRange(AllMemory, "The address range for the CPU-side port") system = Param.System(Parent.any, "System we belong to") diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index ab3e6e3b7..2ef65a13a 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -68,13 +68,24 @@ RubyPort::init() Port * RubyPort::getPort(const std::string &if_name, int idx) { - if (if_name == "port") { - M5Port* cpuPort = new M5Port(csprintf("%s-port%d", name(), idx), + // used by the CPUs to connect the caches to the interconnect, and + // for the x86 case also the interrupt master + if (if_name == "slave") { + M5Port* cpuPort = new M5Port(csprintf("%s-slave%d", name(), idx), this, ruby_system, access_phys_mem); cpu_ports.push_back(cpuPort); return cpuPort; } + // used by the x86 CPUs to connect the interrupt PIO and interrupt slave + // port + if (if_name == "master") { + PioPort* masterPort = new PioPort(csprintf("%s-master%d", name(), idx), + this); + + return masterPort; + } + if (if_name == "pio_port") { // ensure there is only one pio port assert(pio_port == NULL); diff --git a/src/mem/ruby/system/Sequencer.py b/src/mem/ruby/system/Sequencer.py index ddf760f7b..b1e17e052 100644 --- a/src/mem/ruby/system/Sequencer.py +++ b/src/mem/ruby/system/Sequencer.py @@ -34,11 +34,12 @@ from MemObject import MemObject class RubyPort(MemObject): type = 'RubyPort' abstract = True - port = VectorPort("M5 port") + slave = VectorSlavePort("CPU slave port") + master = VectorMasterPort("CPU master port") version = Param.Int(0, "") - pio_port = Port("Ruby_pio_port") + pio_port = MasterPort("Ruby_pio_port") physmem = Param.PhysicalMemory("") - physMemPort = Port("port to physical memory") + physMemPort = MasterPort("port to physical memory") using_ruby_tester = Param.Bool(False, "") using_network_tester = Param.Bool(False, "") access_phys_mem = Param.Bool(True, diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index c45867c85..afdd84fe3 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -46,7 +46,7 @@ from m5.params import * # There are a few things we need that aren't in params.__all__ since # normal users don't need them from m5.params import ParamDesc, VectorParamDesc, \ - isNullPointer, SimObjectVector + isNullPointer, SimObjectVector, Port from m5.proxy import * from m5.proxy import isproxy diff --git a/src/python/m5/params.py b/src/python/m5/params.py index dfc703a40..95958e3e6 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -1,3 +1,15 @@ +# 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-2006 The Regents of The University of Michigan # Copyright (c) 2010-2011 Advanced Micro Devices, Inc. # All rights reserved. @@ -28,6 +40,7 @@ # Authors: Steve Reinhardt # Nathan Binkert # Gabe Black +# Andreas Hansson ##################################################################### # @@ -1324,10 +1337,11 @@ AllMemory = AddrRange(0, MaxAddr) # Port reference: encapsulates a reference to a particular port on a # particular SimObject. class PortRef(object): - def __init__(self, simobj, name): + def __init__(self, simobj, name, role): assert(isSimObject(simobj) or isSimObjectClass(simobj)) self.simobj = simobj self.name = name + self.role = role self.peer = None # not associated with another port yet self.ccConnected = False # C++ port connection done? self.index = -1 # always -1 for non-vector ports @@ -1397,12 +1411,24 @@ class PortRef(object): def ccConnect(self): from m5.internal.pyobject import connectPorts + if self.role == 'SLAVE': + # do nothing and let the master take care of it + return + if self.ccConnected: # already done this return peer = self.peer if not self.peer: # nothing to connect to return + + # check that we connect a master to a slave + if self.role == peer.role: + raise TypeError, \ + "cannot connect '%s' and '%s' due to identical role '%s'" \ + % (peer, self, self.role) + try: + # self is always the master and peer the slave connectPorts(self.simobj.getCCObject(), self.name, self.index, peer.simobj.getCCObject(), peer.name, peer.index) except: @@ -1416,8 +1442,8 @@ class PortRef(object): # A reference to an individual element of a VectorPort... much like a # PortRef, but has an index. class VectorPortElementRef(PortRef): - def __init__(self, simobj, name, index): - PortRef.__init__(self, simobj, name) + def __init__(self, simobj, name, role, index): + PortRef.__init__(self, simobj, name, role) self.index = index def __str__(self): @@ -1426,10 +1452,11 @@ class VectorPortElementRef(PortRef): # A reference to a complete vector-valued port (not just a single element). # Can be indexed to retrieve individual VectorPortElementRef instances. class VectorPortRef(object): - def __init__(self, simobj, name): + def __init__(self, simobj, name, role): assert(isSimObject(simobj) or isSimObjectClass(simobj)) self.simobj = simobj self.name = name + self.role = role self.elements = [] def __str__(self): @@ -1444,7 +1471,7 @@ class VectorPortRef(object): raise TypeError, "VectorPort index must be integer" if key >= len(self.elements): # need to extend list - ext = [VectorPortElementRef(self.simobj, self.name, i) + ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) for i in range(len(self.elements), key+1)] self.elements.extend(ext) return self.elements[key] @@ -1488,34 +1515,62 @@ class VectorPortRef(object): # logical port in the SimObject class, not a particular port on a # SimObject instance. The latter are represented by PortRef objects. class Port(object): - # Port("description") - def __init__(self, *args): - if len(args) == 1: - self.desc = args[0] - else: - raise TypeError, 'wrong number of arguments' - # self.name is set by SimObject class on assignment - # e.g., pio_port = Port("blah") sets self.name to 'pio_port' - # Generate a PortRef for this port on the given SimObject with the # given name def makeRef(self, simobj): - return PortRef(simobj, self.name) + return PortRef(simobj, self.name, self.role) # Connect an instance of this port (on the given SimObject with # the given name) with the port described by the supplied PortRef def connect(self, simobj, ref): self.makeRef(simobj).connect(ref) +class MasterPort(Port): + # MasterPort("description") + def __init__(self, *args): + if len(args) == 1: + self.desc = args[0] + self.role = 'MASTER' + else: + raise TypeError, 'wrong number of arguments' + +class SlavePort(Port): + # SlavePort("description") + def __init__(self, *args): + if len(args) == 1: + self.desc = args[0] + self.role = 'SLAVE' + else: + raise TypeError, 'wrong number of arguments' + # VectorPort description object. Like Port, but represents a vector # of connections (e.g., as on a Bus). class VectorPort(Port): def __init__(self, *args): - Port.__init__(self, *args) self.isVec = True def makeRef(self, simobj): - return VectorPortRef(simobj, self.name) + return VectorPortRef(simobj, self.name, self.role) + +class VectorMasterPort(VectorPort): + # VectorMasterPort("description") + def __init__(self, *args): + if len(args) == 1: + self.desc = args[0] + self.role = 'MASTER' + VectorPort.__init__(self, *args) + else: + raise TypeError, 'wrong number of arguments' + +class VectorSlavePort(VectorPort): + # VectorSlavePort("description") + def __init__(self, *args): + if len(args) == 1: + self.desc = args[0] + self.role = 'SLAVE' + VectorPort.__init__(self, *args) + else: + raise TypeError, 'wrong number of arguments' # 'Fake' ParamDesc for Port references to assign to the _pdesc slot of # proxy objects (via set_param_desc()) so that proxy error messages @@ -1549,6 +1604,7 @@ __all__ = ['Param', 'VectorParam', 'MaxAddr', 'MaxTick', 'AllMemory', 'Time', 'NextEthernetAddr', 'NULL', - 'Port', 'VectorPort'] + 'MasterPort', 'SlavePort', + 'VectorMasterPort', 'VectorSlavePort'] import SimObject diff --git a/src/sim/System.py b/src/sim/System.py index 73124ecb9..88485fcf8 100644 --- a/src/sim/System.py +++ b/src/sim/System.py @@ -39,7 +39,7 @@ class MemoryMode(Enum): vals = ['invalid', 'atomic', 'timing'] class System(MemObject): type = 'System' - system_port = Port("System port") + system_port = MasterPort("System port") @classmethod def export_method_cxx_predecls(cls, code): |