Q: Why there should be a seperate sequencer and driver in an UVM agent?
Q: Why UVM doesn't have single component which combines Driver and Sequencer?
Typically if you are dealing with a packet/frame with layered architecture where lower layer level data encapsulate the higher layer level data. In this case its better to architect the UVC in a layered way. This renders the testbench modular and facilitates the easy reusability and parallel development of Testbench.
Once we do the layered architecture of UVCs, only Bottom UVCs need to have Driver since its attached to the DUT interface, higher leayer UVCs don't need to have driver since they don't attach to any DUT interface instead they attach to the bottom UVCs. Higher layer sequences in the sequencer interact with to the lower level UVCs through sequence item as shown in the above diagram.
At the SoC level verification environment, its often required to use the virutal sequences to sequence/bypass the lower level sequences
Courtesy - Accellera UVM1.1 User guide
As per the guide,
There are three ways in which the virtual sequencer can interact with its subsequencers:
a) “Business as usual”—Virtual subsequencers and subsequencers send transactions simultaneously.
b) Disable subsequencers—Virtual sequencer is the only one driving.
c) Using grab() and ungrab()—Virtual sequencer takes control of the underlying driver(s) for a limited time
(b) and (c) makes the separation of sequencer and driver obvious and hence they are independent components in UVM. Without this seperation, its difficult for virtual sequencer to grab the control of the underlying drivers and achieve interesting scenarios at the SoC/full chip level testbench.