Skip to content

UVM

Myth — "Factory Must Be Used Everywhere"

The overcorrection that every object must go through the UVM factory, corrected with the line that matters — the factory is for things a test might override (components, sequence items, sequences), and forcing it on purely internal, never-overridden helpers in hot paths adds cost without benefit.

UVM Misconceptions Engineers Have · Module 32 · Page 32.2

Having established that UVM is a methodology, this myth overcorrects on one of its mechanisms: the belief that the factory must be used for literally everything. It is the natural overshoot after learning the real rule — that components and transaction items must be created with type_id::create, never new. The correction draws the line precisely: the factory exists to make things overridable from a test, so you use it for what a test might substitute — components, sequence items, sequences — and forcing it on purely internal, never-overridden helper objects, especially in hot paths, adds registration and lookup cost without any benefit. The skill is knowing where overridability matters, not chanting "always the factory."

1. Why This Myth Matters: Overcorrection Has a Cost

You have learned to create components and items with type_id::create; this corrects the overshoot into "everything, always." The rule is right where it matters and wrong where it does not. The factory's entire purpose is substitutability — letting a test override a type from above without editing the environment — so it earns its small cost wherever a test might need that override: every component (so a test can swap a driver or monitor), every transaction item (so a test can inject an error variant), every sequence (so behavior is overridable). The overcorrection is applying it to objects that no test would ever override — an internal bookkeeping struct, a local helper in a scoreboard's hot loop, a transient calculation object you fully control — where the factory adds a registration requirement and a lookup on every construction and buys nothing, because there is nothing to override. The myth produces both needless overhead in hot paths and cargo-cult code that uses the factory without understanding why, which is its own interview tell.

The myth 'factory everywhere' and its correction: use the factory where overridability mattersMyth: type_id::create for every objectthe factory, always, for everything — new is always wrongthe factory, always, for everything — new is always wrongCorrection, part 1: always for the overridablecomponents, transaction items, sequences — a test might substitute them, so factory alwayscomponents, transaction items, sequences — a test might substitute them, so factory alwaysCorrection, part 2: not for internal helpersnever-overridden, fully-controlled objects, especially in hot paths — new is finenever-overridden, fully-controlled objects, especially in hot paths — new is fineThe line: overridabilityuse the factory where a test might override; new for internal, non-overridable helpersuse the factory where a test might override; new for internal, non-overridable helpers
Figure 1 — the myth and its correction. Myth: 'every object must be created with type_id::create.' Correction: the factory exists to make types overridable from a test, so use it for what a test might substitute — all components, all transaction items, all sequences — where the cost of a wrong new (a silently broken override) is high. But for purely internal, never-overridden objects, especially ones created at high rate in a hot path, the factory adds a registration requirement and a per-construction lookup with no benefit, since there is nothing to override; a plain new is appropriate there. The line is overridability: factory where a test might override, pragmatic new for fully-controlled internal helpers.

2. What the Myth Gets Wrong

The corrections address the specific overreaches of "factory everywhere."

  • Myth: "Every object must be created with type_id::create." Correction: The factory is for overridable things. An object no test would ever override — an internal data structure, a local helper — gains nothing from the factory, which only adds the requirement to register it and a lookup on every construction.
  • Myth: "The factory is free, so there is no reason not to use it." Correction: It is cheap but not free — it requires registration and performs a type lookup on each create. In a hot path constructing throwaway objects at high rate, that cost accumulates (see the performance checklist); using new for a purely internal hot object is a legitimate optimization.
  • Myth: "Using new anywhere is a mistake." Correction: new is a mistake for components and items, where it silently breaks overrides — a high-cost error. It is not a mistake for a genuinely local, non-overridable object whose type you fully control; there, new is correct and clearer.
  • Myth: "More factory usage means more correct UVM." Correction: Indiscriminate factory usage is cargo-cult — it signals using a mechanism without understanding its purpose. Correct UVM uses the factory deliberately, where overridability is wanted, not reflexively everywhere.

3. Where the Factory Actually Belongs

The positive statement — where the factory earns its cost, and why it is non-negotiable there.

  • Every component. A test must be able to override a driver, monitor, or any component to specialize the environment, so all components are created via type_id::createnew here silently breaks overrides, the high-cost mistake.
  • Every transaction item. A test injects an error-injecting or extended item by overriding the item type, so items go through the factory too; this is what lets fault tests reuse the agent unchanged.
  • Every sequence. Sequences are overridable so a test can substitute behavior, and they are created through the factory for the same reason.
  • The default leans factory for the architecture. For the structural and stimulus types — the things tests legitimately override — the default is always the factory, because the cost of a wrong new (a broken override discovered late) far exceeds the factory's tiny cost. The exception is the narrow, internal, hot-path helper.

4. Common Misconceptions

5. Interview Insight

6. Interview Questions

No — you use the factory for things a test might override, which means all components, transaction items, and sequences, but a purely internal object that no test would ever override gains nothing from the factory and only pays its cost. The factory's entire purpose is substitutability: type_id::create routes construction through the factory so a test can register an override and substitute a derived type from above without editing the environment. That capability is exactly what you want for components, so a test can swap in an error-injecting driver or an extended monitor; for transaction items, so a test can inject a faulty item; and for sequences, so behavior is overridable. For those, the factory is non-negotiable, and new is a mistake because it silently bypasses the factory and breaks overrides — a high-cost, confusing error. But the factory is not free: it requires the type to be registered and performs a lookup on every create. For an object that is purely internal to a component, fully type-controlled, and never a candidate for override — a small bookkeeping struct, a local helper, a transient calculation object — the factory adds the registration burden and a per-construction lookup and buys nothing, since there is nothing to override. If that object is also created at high rate in a hot path, the lookup is wasted cost. So the line is overridability: use the factory wherever a test might substitute the type, and a plain new is appropriate for genuinely internal, non-overridable helpers. The understanding to convey is that the factory is for overridable things and that forcing it everywhere, including on internal hot-path helpers, is overhead without benefit — which shows you know why the factory exists, not just the rule.

Yes — new is acceptable for a genuinely local, non-overridable object whose type you fully control, while it is a mistake for components and transaction items, where it silently breaks factory overrides. The reflexive teaching is never use new, always type_id::create, and that is correct as a default for the overridable architecture: a component or item built with new bypasses the factory, so any test override of it is silently ignored, and the classic symptom is a registered override that does nothing — a high-cost, hard-to-find bug. So for components, items, and sequences, you always use the factory. But new is not universally wrong. When you construct an object that is purely internal to your component, that no test would ever want to override, and whose type is fixed and under your control — a private data structure, a temporary helper, a local container element — there is nothing for the factory to override, so the factory adds only its registration requirement and per-construction lookup with no benefit. There, new is not just acceptable but clearer and slightly faster, and if the object is created at high rate in a hot loop, avoiding the factory lookup is a legitimate performance choice. The discipline is to base the decision on overridability and cost: factory where a test might override, new where the type is internal and fixed. Stating new is always wrong is the overcorrection; the calibrated position is that new is wrong specifically where it breaks overrides and fine where there are no overrides to break. The understanding to convey is the conditions under which new is acceptable and the high-cost case where it is not, which shows you understand the trade-off rather than reciting an absolute.

The factory's cost is a registration requirement on the class and a type lookup on every type_id::create call, and it matters when objects are created at high rate in a hot path, where the per-construction lookup accumulates. Using the factory requires that the class be registered with the uvm_component_utils or uvm_object_utils macro so it has a type_id the factory knows, and each create performs a lookup to resolve the type — checking for any registered override and returning the right type. For the things you create occasionally — components built once at build time, or even transaction items at typical transaction rates — this cost is negligible and entirely worth the overridability it buys. Where it can matter is a genuinely hot path: an object constructed thousands or millions of times across a run, like a helper created per transaction in a scoreboard or a temporary built inside a tight loop. There the factory lookup, multiplied by the construction rate, becomes a measurable cost, and if that object is internal and never overridden, the cost buys nothing. That is the case where a plain new, or reusing a pooled instance, is the right optimization, as the performance checklist notes. The practical guidance is that you do not micro-optimize by default — you use the factory for the overridable architecture and let its cost be paid where it earns overridability — but where profiling shows construction in a hot path dominating, and the object is internal and non-overridable, dropping to new is justified. The understanding to convey is that the factory cost is registration plus a per-create lookup, negligible for normal construction but real in a hot path, and that it is a profiling-guided trade-off, not a reason to avoid the factory for the architecture where overridability matters.

Because it shows you learned the rule use type_id::create without learning the reason it exists, so you apply it as a ritual rather than for its purpose, which an interviewer reads as cargo-cult understanding. The factory has a specific purpose — to make types overridable from a test — and the right use of it follows from that purpose: you use it where a test might substitute a type, and you understand that where nothing will ever be overridden, it buys nothing. An engineer who understands this uses the factory deliberately for components, items, and sequences and can explain why, and recognizes that an internal, fixed-type helper does not need it. An engineer who has only absorbed always use the factory applies it to everything, including objects no test would override, because they are following a rule rather than reasoning from the rule's purpose — and when asked why, they cannot give a reason beyond that is what you are supposed to do. That inability to justify the boundary is the tell. It is the same pattern as any cargo-cult practice: the form is copied without the function, so it is applied uniformly rather than where it matters, and it cannot adapt to a case the rule did not explicitly cover. Demonstrating understanding means explaining the overridability purpose, where it applies, and where it does not, including the hot-path cost case — which shows you reason from the mechanism's purpose. The understanding to convey is that reflexive uniform application signals rule-following without comprehension, while deliberate application with a justified boundary signals real understanding of why the factory exists, which is the distinction the interview is probing.

You decide by asking whether a test might ever want to override its type, and secondarily what its construction cost is: if a test might substitute it, use the factory; if it is internal and fixed and especially if it is hot, a plain new is appropriate. The primary question is overridability. A type is a factory candidate if substituting it is a meaningful test capability — components, because tests specialize environments by swapping a driver or monitor; transaction items, because tests inject error or extended variants; sequences, because tests override behavior. For all of these the answer is yes, use the factory, and the cost of getting it wrong with new — a silently broken override — makes the factory non-negotiable there. A type is not a factory candidate if it is purely internal to a component, its type is fixed and under your control, and no test would have any reason to replace it — a private helper, a bookkeeping struct, a local container element. For those, the factory adds registration and a lookup with no overridability benefit. The secondary question is cost: if such an internal object is created at high rate in a hot path, avoiding the factory lookup with new or a pool is a justified optimization; if it is created rarely, the factory's cost is negligible and using it for uniformity does little harm either way, so the overridability test dominates. So the decision rule is overridability first — factory if a test might override, new if it is internal and fixed — with hot-path cost reinforcing new for internal objects. The understanding to convey is the overridability-and-cost decision rule, which shows you place each object deliberately rather than applying the factory or new reflexively.

7. Summary

The myth that the factory must be used everywhere overcorrects the real rule — use type_id::create for components and items, not new — into an absolute. The correction draws the line at overridability: the factory exists to make types substitutable from a test, so you use it always for the overridable architecture — every component (so a test can swap it), every transaction item (so a test can inject a variant), every sequence — where a wrong new silently breaks overrides at high cost. But the factory is not free: it requires registration and a per-create lookup, so for a purely internal, never-overridden object — especially one created at high rate in a hot path — it adds cost without benefit, and a plain new is appropriate.

The corrections to state cold: not every object needs the factory — only the overridable ones; the factory is cheap but not free; new is wrong where it breaks overrides and fine where there are none to break; and reflexive factory usage everywhere is cargo-cult, while deliberate usage where overridability matters is real understanding. When asked about the factory, lead with its purpose — overridability — and explain the boundary, because the distinction between using the factory deliberately and chanting it reflexively is exactly what this myth obscures.

8. What Comes Next

You can now place the factory deliberately; next, a myth about randomization:

Next — "Randomization Means Good Verification": the next myth overcorrects on stimulus — the belief that randomizing inputs is, by itself, good verification. The correction is that randomization generates breadth but verifies nothing without checking to confirm correctness and coverage to measure what was reached; random stimulus alone exercises the design blindly rather than proving it correct.