Damien Hedde <damien.he...@greensocs.com> writes:
[...] >> Painted with a big brush, there are two kinds of code in hw/: actual >> device emulation, and "wiring". Both in C, and sometimes in the same .c >> file. >> >> Doing the "wiring" in configuration instead is less powerful (no longer >> Turing complete[2]), but easier to reason about, maintain and change. >> Change is possible even in the field. The obvious separation between >> emulation and wiring is a nice bonus. >> >> The wiring C code supports something not unlike templating: we have a >> number of configuration knobs that deposit something for the wiring C >> code to pick up. >> >> It's rather limited, though: the "variables" are fixed at compile time. >> >> Aside: the handling of variables that doesn't get substituted is wildly >> inconsistent. >> >> Perhaps doing wiring in configuration reduces the maintenance burden to >> a degree where we can mitigate the "defaults gone bad, but no want >> change" issue by offering additional, better things instead of changing >> existing, bad things. I don't know. > > We should be careful with config files, because the configuration > parser can become a real mess. Oh yes. > There are 2 kinds of config files: > > 1. Imperative: an equivalent of QAPI/QMP command script. (eg like CLI > config files Markus proposed). These are easy to handle because they > follow the QMP flow. We do one command after the other, the ordering > of tasks is clear. > > 2. Descriptive: A description of the configuration where we describe > the components and the wiring. This can be really complicated because > we easily end up with ordering/determinism issues when instantiating > them afterwards. For example the configuration parser may have to > solve : Which device do I create first ? I don't think a configuration > parser should have to solve such issues, but I'm not sure if we can > avoid it. Actual instantiation necessarily happens in some order[*]. An imperative configuration dictates the order. A descriptive configuration leaves it to some planner software. Any descriptive configuration can therefore be transformed into an imperative one. *Unless* the planner *also* breaks up components into smaller ones that aren't accessible in the imperative configuration. Example: say the configuration specifies a device and its connections as a unit. Say we have two devices A and B, where A has a connection A->B, and B a connection B->A. A sufficiently smart planner can then create A, B, A->B, B->A. You can't express this imperatively unless connection B->A can be specified separately from device A. I propose to start stupid, i.e. with an imperative, low-level configuration. Then add smarts as we need them. [*] Even if you instantiate stuff concurrently for some reason, there should be at least some conceptual order.