Not direct experience of verilator, but we have extensively used an external simulator (Vivado) through a different approach to true cosimulation which might be relevant here.
This work is encapsulated with Veriutils and Ovenbird. The former is the entry point, and the latter extends Veriutils to target Vivado. The model is that you build python test bench with a bit of (generally helpful) syntactic constraints, and then the tool will automatically wrap the DUT in an equivalent test bench, capturing all the signals and reporting back. It is this wrapped test object which is pure Verilog/VHDL which you can then run in a simulator.
It handles normal signals which have precise timing as well as AXI stream signals in which a convertible BFM is used (for e.g. the case where the DUT uses closed IP which we just model in the python world).
We’ve used this model extensively and with good effect on a large project. The tools are well tested and trusted.
I’m happy to give more assistance if this seems interesting to you…
(I’ve just realised, I haven’t pushed some significant changes to the above repos which don’t change much feature-wise - just filling in a couple of gaps - but were a significant refactoring to make extending easier, so probably relevant to you. I’m just on this now)