The scope of `define
macros and most other compiler directives is a compilation unit. A compilation unit is a stream of source text that a compiler parses. A macro gets defined at the point it appears in the compilation unit and is visible from that point onward.
The scopes defined by modules and other namespaces are irrelevant because macros are pre-processed before any Verilog or SystemVerilog syntax gets recognized. This means you can never have instance specific control over macro definitions.
There is a sight difference between how Verilog and SystemVerilog define a compilation unit.
In Verilog, each compilation unit is a compilation step, or one invocation of a tool that compiles your source code. Some tools only have one compilation step, requiring you to compile all your source code in one step. Other tools (e.g. Modelsim), allow you to compile your code in separate steps. A `define
macro in one compilation step is not visible any other compilation steps unless you re-define it.
SystemVerilog adds the ability to treat each file on the compilers command line as a separate compilation unit. This was needed because SystemVerilog allows you to define things like typedefs and functions outside of a module. Keeping each file a separate compilation unit prevents naming collisions. (This compilation unit behavior is the same in C/C++).
Because of the way people mix legacy Verilog code with SystemVerilog, some tools allow you to choose the Verilog or SystemVerilog behavior of a compilation unit.