I'm wondering how SVF files work when you have different configurations for several FPGAs in a chain (for example depending on a module installed on the board).
TL;DR: JTAG is not easy, but its not hard either. When using SVF/XSVF you need extra files for all possible physical configurations of your scan chain. The more devices you have on JTAG the more benefits you will get from it over an interface like SPI.Let me first summarize some background information so we are on the same page:
The SVF file (or XSVF, which
basically is a binary version of SVF made by xilinx) only specifies what the host should send. So everything you can do over JTAG, you can do over SVF, as long as it does not require any interaction. Its a simple "send this pattern, expect that pattern" format.
So when you are using JTAG, you have all your devices in a daisy chain using the TDI and TDO pins, the TMS pin and the TCK pin are driven by the host and go to all devices in parallel.
Now each device puts an internal shift register between the TDI and TDO pins and a state machine driven by TMS can be used to select if this shift register is the "DATA REGISTER" (DR) or the "INSTRUCTION REGISTER" (IR). Each device has one IR and many DRs, and the value in IR determines with DR is in place.
There are some special values for IR and some conventions about the reset state that allow you to scan the chain and figure out with devices are on there and how large their IR register is and so on. One IR configuration that all devices must support is the BYPASS register. In this mode the chip just put one single FF in the daisy chain when in DR mode.
So when generating the SVF/XSVF file you simply tell the tool how many devices are in the chain, which size the IR registers are and which device your target device is. The SVF file generated will then simply put all other devices in BYPASS mode and add the required number of padding bits to each DR write.
Regarding the overhead: Usually the IR is set once and then hundreds of DR writes follow, each hundreds of bits wide. The IR register becomes much larger if you have many devices in the chain, but the IR is written so seldom that this does not really matter. The DR chain only increases by one additional bit per device on the chain, and the actual DR data for the device you want to program is so large, that the few extra bits do not make a huge difference.
If you have a physical configuration that can change you basically have two options.
The first question is if the socket for you extra module is just empty when the module is not installed or if you have some special connector that just shorts TDI and TDO on the connector so the chain is still intact. If you do not have such a connector, and do not want to place extra components (such as transfer gates) on the motherboard to re-route the TDI and TDO pins, then you must have two chains, one for the motherboard and one for the extra module.
With two chains you can share TDI and TCK between the chains, as long you do not want to run them simultaneously. You obviously need separate TDO pins because the JTAG output pin is not a tristate pin, so you would short out two drivers if you'd connected them together. You also need separate TMS pins. This way you can hold one chain in the JTAG reset state (just resets the jtag interface, not the device) while you talk to the other chain. Thus the chain in reset will ignore the TDI data.
If you have a special connector that shorts the TDI and TDO pins when no module is installed, then you'd normally have two programming files: one for the case where the module is installed and another one for the case where you only have this terminator connected to the port. I theory it would be possible to add the extra fill bits to all DR and IR writes on demand, but I have never seen anybody actually doing that.
If you just want to program a single FPGA, then the SPI interface certainly is much easier. The JTAG interface has a lot of other advantages:
1) You can use it to program and probe a large range of devices, not only FPGAs, and the uC doing that does not need to know anything about them. It just need to know how to play those SVF/XSVF files.
2) You can easily attach a probe to the JTAG port and use the same interface to program the devices directly from a PC, debug processors, perform boundary scans, and many other wonderful things.
3) You do not need any extra per-device pins. This is great because you might want to add an additional IC to your design late in the development process. With JTAG you can simply hang it into the scan chain and all you need are signals that can be re-routed from any nearby chip that already is in the scan chain. With SPI you would have to route an extra slave-select signal all the way from the new chip to the pint where you SPI signal originates (e.g. a uC), and then hope that you still have a free GPIO pin there.