1+ /* ***********************************************************************************
2+ * A full-featured APB UVM Agent
3+ * Copyright (C) 2025 RISCY-Lib Contributors
4+ *
5+ * This program is free software: you can redistribute it and/or modify
6+ * it under the terms of the GNU General Public License as published by
7+ * the Free Software Foundation, either version 3 of the License, or
8+ * (at your option) any later version.
9+ *
10+ * This program is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ * GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License
16+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
17+ ************************************************************************************/
18+
19+ // Class: apb_agent_pkg.apb_agent
20+ class apb_agent # (
21+ `_APB_AGENT_PARAM_DEFS
22+ ) extends uvm_agent ;
23+ `uvm_component_param_utils (apb_agent# (`_APB_AGENT_PARAM_MAP ))
24+ `uvm_type_name_decl (" apb_agent" )
25+
26+ // Group: Class Properties
27+ // //////////////////////////////////////////////////////////////////////////////////////////////
28+
29+ // Reference: m_cfg
30+ // The agent config for this APB Agent
31+ apb_agent_config m_cfg;
32+
33+ // Reference: ap
34+ // Analysis Port for APB Transactions. Internal reference to monitor AP
35+ uvm_analysis_port # (apb_transaction# (`_APB_AGENT_PARAM_MAP )) ap;
36+
37+ // Property: m_monitor
38+ // The UVM Monitor for the APB Agent
39+ apb_monitor # (`_APB_AGENT_PARAM_MAP ) m_monitor;
40+
41+ // Property: m_sequencer
42+ // The UVM Sequencer for the APB Agent
43+ uvm_sequencer # (apb_transaction# (`_APB_AGENT_PARAM_MAP )) m_sequencer;
44+
45+ // Property: m_driver
46+ // The UVM Driver for the APB Agent
47+ apb_driver # (`_APB_AGENT_PARAM_MAP ) m_driver;
48+
49+ // Property: m_cov
50+ // The UVM Coverage Collector for the APB Agent
51+ apb_cov # (`_APB_AGENT_PARAM_MAP ) m_cov;
52+
53+ // Group: Constructors
54+ // //////////////////////////////////////////////////////////////////////////////////////////////
55+
56+ // Constructor: new
57+ function new (string name = " apb_agent" , uvm_component parent = null );
58+ super .new (name, parent);
59+ endfunction : new
60+
61+ // Group: UVM Build Phases
62+ // //////////////////////////////////////////////////////////////////////////////////////////////
63+
64+ // Function: build_phase
65+ // The build_phase for the APB Agent.
66+ //
67+ // This phase performs the following
68+ // - Get the configuration object if not set
69+ // - Check the parameters fall within the APB Spec
70+ // - Build the monitor
71+ // - Build the driver and sequencer if active
72+ // - Build the coverage collector if enabled in the config
73+ virtual function void build_phase (uvm_phase phase);
74+ super .build_phase (phase);
75+
76+ if (m_cfg == null ) begin
77+ if (! uvm_config_db # (apb_agent_config):: get (this , " " , " m_cfg" , m_cfg)) begin
78+ `uvm_fatal (
79+ get_type_name (),
80+ " Cannot get() configuration 'm_cfg' from uvm_config_db. Did you set() it?"
81+ )
82+ end
83+ end
84+
85+ check_params ();
86+
87+ // Instantiate the Monitor (always present)
88+ m_monitor = apb_monitor# (`_APB_AGENT_PARAM_MAP ):: type_id :: create (" m_monitor" , this );
89+ m_monitor.m_cfg = m_cfg;
90+
91+ ap = new (" ap" , this );
92+
93+ // Build the driver and sequencer if active
94+ if (m_cfg.is_active == UVM_ACTIVE ) begin
95+ m_driver = apb_driver# (`_APB_AGENT_PARAM_MAP ):: type_id :: create (" m_driver" , this );
96+ m_driver.m_cfg = m_cfg;
97+
98+ m_sequencer = uvm_sequencer # (apb_transaction# (`_APB_AGENT_PARAM_MAP ))::
99+ type_id :: create (" m_sequencer" , this );
100+ end
101+
102+ // Build the coverage if there is functional coverage
103+ if (m_cfg.has_functional_coverage) begin
104+ m_cov = apb_cov# (`_APB_AGENT_PARAM_MAP ):: type_id :: create (" m_cov" , this );
105+ m_cov.m_cfg = m_cfg;
106+ end
107+
108+ endfunction : build_phase
109+
110+ // Function: connect_phase
111+ // The connect_phase for the APB Agent.
112+ //
113+ // This phase performs the following
114+ // - Connect the monitor to the agent AP
115+ // - Connect the driver and sequencer if the agent is active
116+ // - Connect the monitor and coverage collector if there is functional coverage
117+ virtual function void connect_phase (uvm_phase phase);
118+ super .connect_phase (phase);
119+
120+ // Connect the analysis port of the monitor
121+ ap = m_monitor.ap;
122+
123+ // Connect driver and sequencer if the agent is active
124+ if (m_cfg.is_active == UVM_ACTIVE ) begin
125+ m_driver.seq_item_port.connect (m_sequencer.seq_item_export);
126+ end
127+
128+ // Connect the coverage collector if there is functional coverage
129+ if (m_cfg.has_functional_coverage) begin
130+ m_monitor.ap.connect (m_cov.analysis_export);
131+ end
132+ endfunction : connect_phase
133+
134+ // Function: check_params
135+ // A function which checks that the params fall within the limits perscribed by the spec
136+ virtual function void check_params ();
137+ if (m_cfg.no_parameter_check)
138+ return ;
139+
140+ if (ADDR_WIDTH > 32 ) begin
141+ `uvm_error (
142+ get_type_name (),
143+ $sformatf (
144+ " ADDR_WIDTH is set to %0d . APB Spec requires ADDR_WDITH be <= 32. (Section 2.1)" ,
145+ ADDR_WIDTH
146+ )
147+ )
148+ end
149+
150+ if (! DATA_WIDTH inside { 8 , 16 , 32 } ) begin
151+ `uvm_error (
152+ get_type_name (),
153+ $sformatf (
154+ " DATA_WIDTH is set to %0d . APB Spec requires DATA_WIDTH be 8, 16, or 32. (Section 2.1)" ,
155+ DATA_WIDTH
156+ )
157+ )
158+ end
159+
160+ endfunction : check_params
161+
162+ endclass : apb_agent
0 commit comments