How can module TB trap $fatal from module A
SystemVerilog has a final block that is triggered by the end of simulation

final begin
       log("there was a problem");
      end


You can have as many final blocks as you want, but like initial blocks, there is no guaranteed order among them. There are restrictions about what you can put in a final block, like no time consuming statements. See the 1800-2012 LRM section 9.2.3 Final procedures