changeset f37a6b82f98f in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=f37a6b82f98f
description:
        dev, arm: Rewrite the HDLCD controller

        Rewrite the HDLCD controller to use the new DMA engine and pixel
        pump. This fixes several bugs in the current implementation:

           * Broken/missing interrupt support (VSync, underrun, DMA end)
           * Fragile resolution changes (changing resolutions used
             to cause assertion errors).
           * Support for resolutions with a width that isn't divisible by 32.
           * The pixel clock can now be set dynamically.

        This breaks checkpoint compatibility. Checkpoints can be upgraded with
        the checkpoint conversion script. However, upgraded checkpoints won't
        contain the state of the current frame. That means that HDLCD
        controllers restoring from a converted checkpoint immediately start
        drawing a new frame (i.e, expect timing differences).

diffstat:

 src/dev/arm/RealView.py                 |    18 +-
 src/dev/arm/hdlcd.cc                    |  1146 +++++++++++++-----------------
 src/dev/arm/hdlcd.hh                    |   462 ++++--------
 util/cpt_upgraders/arm-hdlcd-upgrade.py |   109 ++
 4 files changed, 767 insertions(+), 968 deletions(-)

diffs (truncated from 1990 to 300 lines):

diff -r 4808f8c4a47e -r f37a6b82f98f src/dev/arm/RealView.py
--- a/src/dev/arm/RealView.py   Tue Sep 08 19:32:04 2015 -0500
+++ b/src/dev/arm/RealView.py   Fri Sep 11 15:55:46 2015 +0100
@@ -54,6 +54,7 @@
 from SimpleMemory import SimpleMemory
 from Gic import *
 from EnergyCtrl import EnergyCtrl
+from ClockDomain import SrcClockDomain
 
 class AmbaPioDevice(BasicPioDevice):
     type = 'AmbaPioDevice'
@@ -218,23 +219,23 @@
     amba_id = 0x00141111
     enable_capture = Param.Bool(True, "capture frame to 
system.framebuffer.bmp")
 
-
 class HDLcd(AmbaDmaDevice):
     type = 'HDLcd'
     cxx_header = "dev/arm/hdlcd.hh"
-    # For reference, 1024x768MR-16@60  ~= 56 MHz
-    #                1920x1080MR-16@60 ~= 137 MHz
-    #                3840x2160MR-16@60 ~= 533 MHz
-    # Match against the resolution selected in the Linux DTS/DTB file.
-    pixel_clock = Param.Clock('137MHz', "Clock frequency of the pixel clock "
-                                        "(i.e. PXLREFCLK / OSCCLK 5")
     vnc = Param.VncInput(Parent.any, "Vnc server for remote frame buffer "
                                      "display")
     amba_id = 0x00141000
     workaround_swap_rb = Param.Bool(True, "Workaround incorrect color "
                                     "selector order in some kernels")
+    workaround_dma_line_count = Param.Bool(True, "Workaround incorrect "
+                                           "DMA line count (off by 1)")
     enable_capture = Param.Bool(True, "capture frame to 
system.framebuffer.bmp")
 
+    pixel_buffer_size = Param.MemorySize32("2kB", "Size of address range")
+
+    pxl_clk = Param.ClockDomain("Pixel clock source")
+    pixel_chunk = Param.Unsigned(32, "Number of pixels to handle in one batch")
+
 class RealView(Platform):
     type = 'RealView'
     cxx_header = "dev/arm/realview.hh"
@@ -518,7 +519,8 @@
     timer0 = Sp804(int_num0=34, int_num1=34, pio_addr=0x1C110000, 
clock0='1MHz', clock1='1MHz')
     timer1 = Sp804(int_num0=35, int_num1=35, pio_addr=0x1C120000, 
clock0='1MHz', clock1='1MHz')
     clcd   = Pl111(pio_addr=0x1c1f0000, int_num=46)
-    hdlcd  = HDLcd(pio_addr=0x2b000000, int_num=117)
+    hdlcd  = HDLcd(pxl_clk=realview_io.osc_pxl,
+                   pio_addr=0x2b000000, int_num=117)
     kmi0   = Pl050(pio_addr=0x1c060000, int_num=44)
     kmi1   = Pl050(pio_addr=0x1c070000, int_num=45, is_mouse=True)
     vgic   = VGic(vcpu_addr=0x2c006000, hv_addr=0x2c004000, ppint=25)
diff -r 4808f8c4a47e -r f37a6b82f98f src/dev/arm/hdlcd.cc
--- a/src/dev/arm/hdlcd.cc      Tue Sep 08 19:32:04 2015 -0500
+++ b/src/dev/arm/hdlcd.cc      Fri Sep 11 15:55:46 2015 +0100
@@ -35,6 +35,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Chris Emmons
+ *          Andreas Sandberg
  */
 
 #include "dev/arm/hdlcd.hh"
@@ -42,145 +43,175 @@
 #include "base/vnc/vncinput.hh"
 #include "base/output.hh"
 #include "base/trace.hh"
+#include "debug/Checkpoint.hh"
 #include "debug/HDLcd.hh"
-#include "debug/Uart.hh"
 #include "dev/arm/amba_device.hh"
 #include "dev/arm/base_gic.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
+#include "params/HDLcd.hh"
 #include "sim/system.hh"
 
 using std::vector;
 
 
 // initialize hdlcd registers
-HDLcd::HDLcd(const Params *p)
-    : AmbaDmaDevice(p), version(VERSION_RESETV),
-      int_rawstat(0), int_clear(0), int_mask(0), int_status(0),
+HDLcd::HDLcd(const HDLcdParams *p)
+    : AmbaDmaDevice(p, 0xFFFF),
+      // Parameters
+      vnc(p->vnc),
+      workaroundSwapRB(p->workaround_swap_rb),
+      workaroundDmaLineCount(p->workaround_dma_line_count),
+      addrRanges{RangeSize(pioAddr, pioSize)},
+      enableCapture(p->enable_capture),
+      pixelBufferSize(p->pixel_buffer_size),
+
+      // Registers
+      version(VERSION_RESETV),
+      int_rawstat(0), int_mask(0),
+
       fb_base(0), fb_line_length(0), fb_line_count(0), fb_line_pitch(0),
       bus_options(BUS_OPTIONS_RESETV),
+
       v_sync(0), v_back_porch(0), v_data(0), v_front_porch(0),
       h_sync(0), h_back_porch(0), h_data(0), h_front_porch(0),
-      polarities(0), command(0), pixel_format(0),
+      polarities(0),
+
+      command(0),
+
+      pixel_format(0),
       red_select(0), green_select(0), blue_select(0),
-      pixelClock(p->pixel_clock),
-      fb(0, 0), vnc(p->vnc), bmp(&fb), pic(NULL),
-      frameReadStartTime(0),
-      dmaStartAddr(0), dmaCurAddr(0), dmaMaxAddr(0), dmaPendingNum(0),
-      frameUnderrun(false), pixelBufferSize(0),
-      pixelIndex(0), doUpdateParams(false), frameUnderway(false),
-      dmaBytesInFlight(0),
-      startFrameEvent(this), endFrameEvent(this), renderPixelEvent(this),
-      fillPixelBufferEvent(this), intEvent(this),
-      dmaDoneEventAll(MAX_OUTSTANDING_DMA_REQ_CAPACITY, this),
-      dmaDoneEventFree(MAX_OUTSTANDING_DMA_REQ_CAPACITY),
-      enableCapture(p->enable_capture),
-      workaround_swap_rb(p->workaround_swap_rb)
+
+      // Other
+      bmp(&pixelPump.fb), pic(NULL), conv(PixelConverter::rgba8888_le),
+      pixelPump(*this, *p->pxl_clk, p->pixel_chunk)
 {
-    pioSize = 0xFFFF;
-
-    for (int i = 0; i < MAX_OUTSTANDING_DMA_REQ_CAPACITY; ++i)
-        dmaDoneEventFree[i] = &dmaDoneEventAll[i];
-
     if (vnc)
-        vnc->setFrameBuffer(&fb);
+        vnc->setFrameBuffer(&pixelPump.fb);
 }
 
 HDLcd::~HDLcd()
 {
 }
 
+void
+HDLcd::serialize(CheckpointOut &cp) const
+{
+    DPRINTF(Checkpoint, "Serializing ARM HDLCD\n");
+
+    SERIALIZE_SCALAR(int_rawstat);
+    SERIALIZE_SCALAR(int_mask);
+
+    SERIALIZE_SCALAR(fb_base);
+    SERIALIZE_SCALAR(fb_line_length);
+    SERIALIZE_SCALAR(fb_line_count);
+    SERIALIZE_SCALAR(fb_line_pitch);
+    SERIALIZE_SCALAR(bus_options);
+
+    SERIALIZE_SCALAR(v_sync);
+    SERIALIZE_SCALAR(v_back_porch);
+    SERIALIZE_SCALAR(v_data);
+    SERIALIZE_SCALAR(v_front_porch);
+
+    SERIALIZE_SCALAR(h_sync);
+    SERIALIZE_SCALAR(h_back_porch);
+    SERIALIZE_SCALAR(h_data);
+    SERIALIZE_SCALAR(h_front_porch);
+
+    SERIALIZE_SCALAR(polarities);
+
+    SERIALIZE_SCALAR(command);
+    SERIALIZE_SCALAR(pixel_format);
+    SERIALIZE_SCALAR(red_select);
+    SERIALIZE_SCALAR(green_select);
+    SERIALIZE_SCALAR(blue_select);
+
+    SERIALIZE_OBJ(pixelPump);
+    if (enabled())
+        dmaEngine->serializeSection(cp, "dmaEngine");
+}
+
+void
+HDLcd::unserialize(CheckpointIn &cp)
+{
+    DPRINTF(Checkpoint, "Unserializing ARM HDLCD\n");
+
+    UNSERIALIZE_SCALAR(int_rawstat);
+    UNSERIALIZE_SCALAR(int_mask);
+
+    UNSERIALIZE_SCALAR(fb_base);
+    UNSERIALIZE_SCALAR(fb_line_length);
+    UNSERIALIZE_SCALAR(fb_line_count);
+    UNSERIALIZE_SCALAR(fb_line_pitch);
+    UNSERIALIZE_SCALAR(bus_options);
+
+    UNSERIALIZE_SCALAR(v_sync);
+    UNSERIALIZE_SCALAR(v_back_porch);
+    UNSERIALIZE_SCALAR(v_data);
+    UNSERIALIZE_SCALAR(v_front_porch);
+
+    UNSERIALIZE_SCALAR(h_sync);
+    UNSERIALIZE_SCALAR(h_back_porch);
+    UNSERIALIZE_SCALAR(h_data);
+    UNSERIALIZE_SCALAR(h_front_porch);
+
+    UNSERIALIZE_SCALAR(polarities);
+
+    UNSERIALIZE_SCALAR(command);
+    UNSERIALIZE_SCALAR(pixel_format);
+    UNSERIALIZE_SCALAR(red_select);
+    UNSERIALIZE_SCALAR(green_select);
+    UNSERIALIZE_SCALAR(blue_select);
+
+    {
+        // Try to unserialize the pixel pump. It might not exist if
+        // we're unserializing an old checkpoint.
+        ScopedCheckpointSection sec(cp, "pixelPump");
+        if (cp.sectionExists(Serializable::currentSection()))
+            pixelPump.unserialize(cp);
+    }
+
+    if (enabled()) {
+        // Create the DMA engine and read its state from the
+        // checkpoint. We don't need to worry about the pixel pump as
+        // it is a proper SimObject.
+        createDmaEngine();
+        dmaEngine->unserializeSection(cp, "dmaEngine");
+
+        conv = pixelConverter();
+    }
+}
+
+void
+HDLcd::drainResume()
+{
+    AmbaDmaDevice::drainResume();
+
+    // We restored from an old checkpoint without a pixel pump, start
+    // an new refresh. This typically happens when restoring from old
+    // checkpoints.
+    if (enabled() && !pixelPump.active())
+        pixelPump.start(displayTimings());
+
+    // We restored from a checkpoint and need to update the VNC server
+    if (pixelPump.active() && vnc)
+        vnc->setDirty();
+}
+
 // read registers and frame buffer
 Tick
 HDLcd::read(PacketPtr pkt)
 {
-    uint32_t data = 0;
-    const Addr daddr = pkt->getAddr() - pioAddr;
+    assert(pkt->getAddr() >= pioAddr &&
+           pkt->getAddr() < pioAddr + pioSize);
 
-    DPRINTF(HDLcd, "read register BASE+0x%04x size=%d\n", daddr,
-            pkt->getSize());
+    const Addr daddr(pkt->getAddr() - pioAddr);
+    panic_if(pkt->getSize() != 4,
+             "Unhandled read size (address: 0x.4x, size: %u)",
+             daddr, pkt->getSize());
 
-    assert(pkt->getAddr() >= pioAddr &&
-            pkt->getAddr() < pioAddr + pioSize &&
-            pkt->getSize() == 4);
-
-    switch (daddr) {
-      case Version:
-        data = version;
-        break;
-      case Int_RawStat:
-        data = int_rawstat;
-        break;
-      case Int_Clear:
-        panic("HDLCD INT_CLEAR register is Write-Only\n");
-        break;
-      case Int_Mask:
-        data = int_mask;
-        break;
-      case Int_Status:
-        data = int_status;
-        break;
-      case Fb_Base:
-        data = fb_base;
-        break;
-      case Fb_Line_Length:
-        data = fb_line_length;
-        break;
-      case Fb_Line_Count:
-        data = fb_line_count;
-        break;
-      case Fb_Line_Pitch:
-        data = fb_line_pitch;
-        break;
-      case Bus_Options:
-        data = bus_options;
-        break;
-      case V_Sync:
-        data = v_sync;
-        break;
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to