From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:38040) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R4Bxv-0005Ea-DB for qemu-devel@nongnu.org; Thu, 15 Sep 2011 09:26:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1R4Bxt-0007P6-9B for qemu-devel@nongnu.org; Thu, 15 Sep 2011 09:26:55 -0400 Received: from mail-gy0-f173.google.com ([209.85.160.173]:52085) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R4Bxt-0007Ou-46 for qemu-devel@nongnu.org; Thu, 15 Sep 2011 09:26:53 -0400 Received: by gye5 with SMTP id 5so2562635gye.4 for ; Thu, 15 Sep 2011 06:26:52 -0700 (PDT) Message-ID: <4E71FD19.6050606@codemonkey.ws> Date: Thu, 15 Sep 2011 08:26:49 -0500 From: Anthony Liguori MIME-Version: 1.0 References: <4E70EC90.8000904@us.ibm.com> <4E719F7C.10700@redhat.com> In-Reply-To: <4E719F7C.10700@redhat.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [RFC] Plan for moving forward with QOM List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Paolo Bonzini Cc: Peter Maydell , Jan Kiszka , qemu-devel , Markus Armbruster , Gerd Hoffmann , "Edgar E. Iglesias" On 09/15/2011 01:47 AM, Paolo Bonzini wrote: > On 09/14/2011 08:04 PM, Anthony Liguori wrote: >> The concept of busses are implemented as an >> interface that a device implements. > > I noticed that you haven't written in the document how to make devices reside on > a particular bus (PCI, ISA, I2C, ...). > > The three possibilities for this are: > > * a device implements an interface. I would rule this out because for most buses > the devices will need to store some data (PCI: configuration data, pointer to > the parent bus; ISA: pointer to the parent bus). Interfaces are > implementation-only, so you have to place the data in each device and cause > massive code duplication. I agree. > > * a device inherits from an abstract class, e.g. PCIDevice. It is useful to see > how the inheritance tree would look like for two devices with a common chipset > and multiple interfaces: > > Device > NE2000 > PCIDevice > PCI_NE2000 ------> includes a NE2000 > ISA_NE2000 ------> includes a NE2000 I think this model is the closest to what we have today and is the most obvious. For something like ne2k, I would expect: class NE2000 : public Device { // ne2k public functions }; class PCI_NE2000 : public PciDevice { // implement PCI functions by calling ne2k public functions NE2000 ne2k; }; class ISA_NE2000 : public IsaDevice { // implement ISA functions by calling ne2k public functions NE2000 ne2k; }; > * a device is composed with a connector object. There is no PCIDevice class > anymore, so the bus has an array of socket instead. The case above > would look like this > > Device > NE2000 (abstract) > PCI_NE2000 ------> includes a PCIConnector > ISA_NE2000 ------> includes an ISAConnector > > Or, if you insist on a closer mapping of real hardware, where there are no > abstract classes, it would look like this: > > Device > NE2000 > PCI_NE2000 ------> includes an NE2000 and a PCIConnector > ISA_NE2000 ------> includes an NE2000 and an ISAConnector I think there are two ways to view this: class PciDevice : public Device { PciConnector connector; // init function registers closures with connector that dispatch // to abstract functions }; Or: class PciConnector : public PciDevice { // provides interfaces to register closures which implement // PCI abstract functions }; I personally lean toward the later as I don't think the PciConnector model really does map all that well to hardware (normally, at least). I think this is much closer to how real hardware actually works. > > Advantages of abstract classes are pretty obvious, so I will just list them: it > is more similar to what is done in QDev, and perhaps it is more intuitive. > > > Advantages of connectors include: > > * it is more flexible: it lets you choose between a more abstract and a more > low-level representation (the two hierarchies above); > > * you have the option of showing a simpler device tree to the user, without the > internal composition. This is important because, unlike QDev, composition in QOM > is explicit. So QOM would place NIC properties in NE2000, not in *_NE2000 (right?). > > * related to this, it keeps property names more stable. If I understand > correctly, if the device starts as ISA-only or PCI-only, i.e.: > > Device > PCIDevice > PCI_NE2000 > > and later you change it to support multiple buses, suddenly properties would > have to be addressed differently to account for the composition of NE2000 inside > PCI_NE2000. You could I guess implement "forwarder properties", but that would > also lead to more boilerplate code. > > Any other opinions? The properties thing is definitely an interesting point, but I'm not sure how far you can push it. If you start out with a NE2000 device that is ISA and you decide to abstract it to a shared model, all you need to do is keep the ISA NE2000 device named NE2000 and call the common chip and PCI bridge something else. I really think it's important to keep the simple cases simple. I think any model where you don't do: class E1000 : public PciDevice { }; Is unnecessarily complicated. If it's too complicated, conversions will be much slower to do and will be more likely to be done wrong. Regards, Anthony Liguori > Paolo >