In reply to p*9s$eW:
Just a few style comments. The monitor class came up first so I’ll start there.
- Always think about reusability. Give a meaningful prefix name to the class, even if it is just “cpu_monitor” instead of “monitor”.
- The new() method is to initialize simple properties.
- Use the build_phase() to construct the testbench, including the TLM port.
- Always create your components and transactions, don’t call new(), otherwise you can’t override them later.
- Reduce the number of messages in the log file. For example, “Build state complete” should be UVM_HIGH so it doesn’t normally print.
- Split up the monitor run_phase() into two separate tasks, get_inputs() and get_outputs() to make it more modular. Each could have its own forever loop.
- Your monitor only ever constructs one transaction object, then constantly writes over the properties, again and again. If your scoreboard ever has a delay between receiving a transaction handle and reading it, the object’s values could have been changed.
Also, the scoreboard’s write() method could process the incoming transaction handles immediately, without putting them in a queue. Trigger an event when pc_addr==17. Then the run_phase() just blocks on that event.