I start off every post with some vocal exclamation, so gah!
(All this is from memory, so forgive any unintentional mistakes.)
Lattice IP Express allows you to create PCIe cores. For compilation, you are given 2 NGO files, xxx.ngo and xxx_pcs.ngo. For simulation you are given an obfuscated behavioral model of PCIe and the sources for the pcs NGO. (Why do they compile those sources to xxx_pcs.ngo? I guess it's to save the user from complications, and to save them from using the define files discussed next.) The simulation files are all controlled through files with various `defines in them. These `defines control the compilation of both the beh and pcs files. This is a major problem in Modelsim!
First off, you run into the issue that you can't have 2 cores with different simulation `defines running in the same design. For example I have a DUT (Device Under Test) with Wishbone and a BFM (Bus Functional Model) without it. This can't work b/c the same module names are used in both instances, even when you gave the cores different top level names during IP Express creation!
Next issue is that you can try to change the module names, but the behavioral model has a large amount of tiny modules with obfuscated names and with no easy way to go over the file and rename them all. You can do it, but it would take a nice sed script or some other method, and it would be annoying... The other modules of course could be renamed much easier. Next problem is that the defines are of course the same names, so you'd have to rename those, or compile the files from a top level .v file so the defines stay local at least with the -sv switch. All sorts of headaches involved.
Create separate libraries for the simulation core and the DUT core. Use Modelsim's trick to get vsim to work properly... What is that trick you ask? By setting the first search library as work in the vsim command, Modelsim will perform a search for modules beginning with the library that the module is instantiated inside of.
This won't work:
vsim top_tb -L pcie_sim_work -L pcie_endpoint_work
This will work:
vsim top_tb -L work -L pcie_sim_work -L pcie_endpoint_work
(Note: Lattice requires pcsd_mti_work also... so add -L pcsd_mti_work after mapping the library)
Modelsim discusses this special case in their reference manual under "Handling sub-modules with common names":
"When you specify -L work first in the search library arguments you are directing
vsim to search for the instantiated module or UDP in the library that contains the module
that does the instantiation."