changeset 2f1a3e335255 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=2f1a3e335255
description:
        MEM: Make the bus bridge unidirectional and fixed address range

        This patch makes the bus bridge uni-directional and specialises the
        bus ports to be a master port and a slave port. This greatly
        simplifies the assumptions on both sides as either port only has to
        deal with requests or responses. The following patches introduce the
        notion of master and slave ports, and would not be possible without
        this split of responsibilities.

        In making the bridge unidirectional, the address range mechanism of
        the bridge is also changed. For the cases where communication is
        taking place both ways, an additional bridge is needed. This causes
        issues with the existing mechanism, as the busses cannot determine
        when to stop iterating the address updates from the two bridges. To
        avoid this issue, and also greatly simplify the specification, the
        bridge now has a fixed set of address ranges, specified at creation
        time.

diffstat:

 configs/common/FSConfig.py                    |   79 ++++-
 configs/example/fs.py                         |   24 +-
 src/dev/arm/RealView.py                       |   31 +-
 src/mem/Bridge.py                             |   16 +-
 src/mem/bridge.cc                             |  395 +++++++++++++++++--------
 src/mem/bridge.hh                             |  354 ++++++++++++++++++-----
 tests/configs/pc-o3-timing.py                 |    2 -
 tests/configs/pc-simple-atomic.py             |    2 -
 tests/configs/pc-simple-timing.py             |    2 -
 tests/configs/realview-o3-dual.py             |    2 -
 tests/configs/realview-o3.py                  |    2 -
 tests/configs/realview-simple-atomic-dual.py  |    2 -
 tests/configs/realview-simple-atomic.py       |    2 -
 tests/configs/realview-simple-timing-dual.py  |    2 -
 tests/configs/realview-simple-timing.py       |    2 -
 tests/configs/tsunami-inorder.py              |    2 -
 tests/configs/tsunami-o3-dual.py              |    2 -
 tests/configs/tsunami-o3.py                   |    2 -
 tests/configs/tsunami-simple-atomic-dual.py   |    2 -
 tests/configs/tsunami-simple-atomic.py        |    2 -
 tests/configs/tsunami-simple-timing-dual.py   |    2 -
 tests/configs/tsunami-simple-timing.py        |    2 -
 tests/configs/twosys-tsunami-simple-atomic.py |   11 +
 23 files changed, 661 insertions(+), 281 deletions(-)

diffs (truncated from 1527 to 300 lines):

diff -r 7f762428a9f5 -r 2f1a3e335255 configs/common/FSConfig.py
--- a/configs/common/FSConfig.py        Tue Jan 17 12:55:09 2012 -0600
+++ b/configs/common/FSConfig.py        Tue Jan 17 12:55:09 2012 -0600
@@ -56,6 +56,7 @@
 
 
 def makeLinuxAlphaSystem(mem_mode, mdesc = None):
+    IO_address_space_base = 0x80000000000
     class BaseTsunami(Tsunami):
         ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0)
         ide = IdeController(disks=[Parent.disk0, Parent.disk2],
@@ -68,10 +69,13 @@
     self.readfile = mdesc.script()
     self.iobus = Bus(bus_id=0)
     self.membus = MemBus(bus_id=1)
-    self.bridge = Bridge(delay='50ns', nack_delay='4ns')
+    # By default the bridge responds to all addresses above the I/O
+    # base address (including the PCI config space)
+    self.bridge = Bridge(delay='50ns', nack_delay='4ns',
+                         ranges = [AddrRange(IO_address_space_base, Addr.max)])
     self.physmem = PhysicalMemory(range = AddrRange(mdesc.mem()))
-    self.bridge.side_a = self.iobus.port
-    self.bridge.side_b = self.membus.port
+    self.bridge.master = self.iobus.port
+    self.bridge.slave = self.membus.port
     self.physmem.port = self.membus.port
     self.disk0 = CowIdeDisk(driveID='master')
     self.disk2 = CowIdeDisk(driveID='master')
@@ -146,6 +150,10 @@
     return self
 
 def makeSparcSystem(mem_mode, mdesc = None):
+    # Constants from iob.cc and uart8250.cc
+    iob_man_addr = 0x9800000000
+    uart_pio_size = 8
+
     class CowMmDisk(MmDisk):
         image = CowDiskImage(child=RawDiskImage(read_only=True),
                              read_only=False)
@@ -166,8 +174,8 @@
     self.t1000.attachIO(self.iobus)
     self.physmem = PhysicalMemory(range = AddrRange(Addr('1MB'), size = 
'64MB'), zero = True)
     self.physmem2 = PhysicalMemory(range = AddrRange(Addr('2GB'), size 
='256MB'), zero = True)
-    self.bridge.side_a = self.iobus.port
-    self.bridge.side_b = self.membus.port
+    self.bridge.master = self.iobus.port
+    self.bridge.slave = self.membus.port
     self.physmem.port = self.membus.port
     self.physmem2.port = self.membus.port
     self.rom.port = self.membus.port
@@ -178,6 +186,25 @@
     self.disk0 = CowMmDisk()
     self.disk0.childImage(disk('disk.s10hw2'))
     self.disk0.pio = self.iobus.port
+
+    # The puart0 and hvuart are placed on the IO bus, so create ranges
+    # for them. The remaining IO range is rather fragmented, so poke
+    # holes for the iob and partition descriptors etc.
+    self.bridge.ranges = \
+        [
+        AddrRange(self.t1000.puart0.pio_addr,
+                  self.t1000.puart0.pio_addr + uart_pio_size - 1),
+        AddrRange(self.disk0.pio_addr,
+                  self.t1000.fake_jbi.pio_addr +
+                  self.t1000.fake_jbi.pio_size - 1),
+        AddrRange(self.t1000.fake_clk.pio_addr,
+                  iob_man_addr - 1),
+        AddrRange(self.t1000.fake_l2_1.pio_addr,
+                  self.t1000.fake_ssi.pio_addr +
+                  self.t1000.fake_ssi.pio_size - 1),
+        AddrRange(self.t1000.hvuart.pio_addr,
+                  self.t1000.hvuart.pio_addr + uart_pio_size - 1)
+        ]
     self.reset_bin = binary('reset_new.bin')
     self.hypervisor_bin = binary('q_new.bin')
     self.openboot_bin = binary('openboot_new.bin')
@@ -206,8 +233,8 @@
     self.membus = MemBus(bus_id=1)
     self.membus.badaddr_responder.warn_access = "warn"
     self.bridge = Bridge(delay='50ns', nack_delay='4ns')
-    self.bridge.side_a = self.iobus.port
-    self.bridge.side_b = self.membus.port
+    self.bridge.master = self.iobus.port
+    self.bridge.slave = self.membus.port
 
     self.mem_mode = mem_mode
 
@@ -261,7 +288,7 @@
         self.boot_osflags = boot_flags
 
     self.physmem.port = self.membus.port
-    self.realview.attachOnChipIO(self.membus)
+    self.realview.attachOnChipIO(self.membus, self.bridge)
     self.realview.attachIO(self.iobus)
     self.intrctrl = IntrControl()
     self.terminal = Terminal()
@@ -287,8 +314,8 @@
     self.membus = MemBus(bus_id=1)
     self.bridge = Bridge(delay='50ns', nack_delay='4ns')
     self.physmem = PhysicalMemory(range = AddrRange('1GB'))
-    self.bridge.side_a = self.iobus.port
-    self.bridge.side_b = self.membus.port
+    self.bridge.master = self.iobus.port
+    self.bridge.slave = self.membus.port
     self.physmem.port = self.membus.port
     self.disk0 = CowIdeDisk(driveID='master')
     self.disk2 = CowIdeDisk(driveID='master')
@@ -316,14 +343,42 @@
     return IO_address_space_base + port
 
 def connectX86ClassicSystem(x86_sys):
+    # Constants similar to x86_traits.hh
+    IO_address_space_base = 0x8000000000000000
+    pci_config_address_space_base = 0xc000000000000000
+    interrupts_address_space_base = 0xa000000000000000
+    APIC_range_size = 1 << 12;
+
     x86_sys.membus = MemBus(bus_id=1)
     x86_sys.physmem.port = x86_sys.membus.port
 
     # North Bridge
     x86_sys.iobus = Bus(bus_id=0)
     x86_sys.bridge = Bridge(delay='50ns', nack_delay='4ns')
-    x86_sys.bridge.side_a = x86_sys.iobus.port
-    x86_sys.bridge.side_b = x86_sys.membus.port
+    x86_sys.bridge.master = x86_sys.iobus.port
+    x86_sys.bridge.slave = x86_sys.membus.port
+    # Allow the bridge to pass through the IO APIC (two pages),
+    # everything in the IO address range up to the local APIC, and
+    # then the entire PCI address space and beyond
+    x86_sys.bridge.ranges = \
+        [
+        AddrRange(x86_sys.pc.south_bridge.io_apic.pio_addr,
+                  x86_sys.pc.south_bridge.io_apic.pio_addr +
+                  APIC_range_size - 1),
+        AddrRange(IO_address_space_base,
+                  interrupts_address_space_base - 1),
+        AddrRange(pci_config_address_space_base,
+                  Addr.max)
+        ]
+
+    # Create a bridge from the IO bus to the memory bus to allow access to
+    # the local APIC (two pages)
+    x86_sys.iobridge = Bridge(delay='50ns', nack_delay='4ns')
+    x86_sys.iobridge.slave = x86_sys.iobus.port
+    x86_sys.iobridge.master = x86_sys.membus.port
+    x86_sys.iobridge.ranges = [AddrRange(interrupts_address_space_base,
+                                         interrupts_address_space_base +
+                                         APIC_range_size - 1)]
 
     # connect the io bus
     x86_sys.pc.attachIO(x86_sys.iobus)
diff -r 7f762428a9f5 -r 2f1a3e335255 configs/example/fs.py
--- a/configs/example/fs.py     Tue Jan 17 12:55:09 2012 -0600
+++ b/configs/example/fs.py     Tue Jan 17 12:55:09 2012 -0600
@@ -1,4 +1,4 @@
-# Copyright (c) 2010 ARM Limited
+# Copyright (c) 2010-2011 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -157,23 +157,19 @@
 
 CacheConfig.config_cache(options, test_sys)
 
+if bm[0]:
+    mem_size = bm[0].mem()
+else:
+    mem_size = SysConfig().mem()
 if options.caches or options.l2cache:
-    if bm[0]:
-        mem_size = bm[0].mem()
-    else:
-        mem_size = SysConfig().mem()
-    # For x86, we need to poke a hole for interrupt messages to get back to the
-    # CPU. These use a portion of the physical address space which has a
-    # non-zero prefix in the top nibble. Normal memory accesses have a 0
-    # prefix.
-    if buildEnv['TARGET_ISA'] == 'x86':
-        test_sys.bridge.filter_ranges_a=[AddrRange(0, Addr.max >> 4)]
-    else:
-        test_sys.bridge.filter_ranges_a=[AddrRange(0, Addr.max)]
-    test_sys.bridge.filter_ranges_b=[AddrRange(mem_size)]
     test_sys.iocache = IOCache(addr_range=mem_size)
     test_sys.iocache.cpu_side = test_sys.iobus.port
     test_sys.iocache.mem_side = test_sys.membus.port
+else:
+    test_sys.iobridge = Bridge(delay='50ns', nack_delay='4ns',
+                               ranges = [AddrRange(0, mem_size)])
+    test_sys.iobridge.slave = test_sys.iobus.port
+    test_sys.iobridge.master = test_sys.membus.port
 
 for i in xrange(np):
     if options.fastmem:
diff -r 7f762428a9f5 -r 2f1a3e335255 src/dev/arm/RealView.py
--- a/src/dev/arm/RealView.py   Tue Jan 17 12:55:09 2012 -0600
+++ b/src/dev/arm/RealView.py   Tue Jan 17 12:55:09 2012 -0600
@@ -1,4 +1,4 @@
-# Copyright (c) 2009 ARM Limited
+# Copyright (c) 2009-2011 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -177,12 +177,18 @@
     rtc_fake      = AmbaFake(pio_addr=0x10017000, amba_id=0x41031)
 
 
-    # Attach I/O devices that are on chip
-    def attachOnChipIO(self, bus):
+    # 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
+       # 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, 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
@@ -248,10 +254,16 @@
 
 
 
-    # Attach I/O devices that are on chip
-    def attachOnChipIO(self, bus):
+    # 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
+       # 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
@@ -329,10 +341,15 @@
     usb_fake       = IsaFake(pio_addr=0xFB000000, pio_size=0x1ffff)
 
 
-    # Attach I/O devices that are on chip
-    def attachOnChipIO(self, bus):
+    # 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
+       # 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),
+                        AddrRange(self.local_cpu_timer.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
diff -r 7f762428a9f5 -r 2f1a3e335255 src/mem/Bridge.py
--- a/src/mem/Bridge.py Tue Jan 17 12:55:09 2012 -0600
+++ b/src/mem/Bridge.py Tue Jan 17 12:55:09 2012 -0600
@@ -31,16 +31,12 @@
 
 class Bridge(MemObject):
     type = 'Bridge'
-    side_a = Port('Side A port')
-    side_b = Port('Side B port')
-    req_size_a = Param.Int(16, "The number of requests to buffer")
-    req_size_b = Param.Int(16, "The number of requests to buffer")
-    resp_size_a = Param.Int(16, "The number of requests to buffer")
-    resp_size_b = Param.Int(16, "The number of requests to buffer")
+    slave = Port('Slave port')
+    master = Port('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")
     nack_delay = Param.Latency('0ns', "The latency of this bridge")
     write_ack = Param.Bool(False, "Should this bridge ack writes")
-    filter_ranges_a = VectorParam.AddrRange([],
-            "What addresses shouldn't be passed through the side of the 
bridge")
-    filter_ranges_b = VectorParam.AddrRange([],
-            "What addresses shouldn't be passed through the side of the 
bridge")
+    ranges = VectorParam.AddrRange([AllMemory],
+                                   "Address ranges to pass through the bridge")
diff -r 7f762428a9f5 -r 2f1a3e335255 src/mem/bridge.cc
--- a/src/mem/bridge.cc Tue Jan 17 12:55:09 2012 -0600
+++ b/src/mem/bridge.cc Tue Jan 17 12:55:09 2012 -0600
@@ -1,5 +1,16 @@
-
 /*
+ * Copyright (c) 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
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to