OpenCores
URL https://opencores.org/ocsvn/lpffir/lpffir/trunk

Subversion Repositories lpffir

[/] [lpffir/] [trunk/] [uvm/] [tools/] [easier_uvm_gen/] [easier_uvm_gen.pl] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 vladimirar
#!/usr/bin/perl
2
##
3
##----------------------------------------------------------------------
4
## Copyright (c) 2013-2016 by Doulos Ltd.
5
##
6
## Licensed under the Apache License, Version 2.0 (the "License");
7
## you may not use this file except in compliance with the License.
8
## You may obtain a copy of the License at
9
##
10
##     http://www.apache.org/licenses/LICENSE-2.0
11
##
12
## Unless required by applicable law or agreed to in writing, software
13
## distributed under the License is distributed on an "AS IS" BASIS,
14
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
## See the License for the specific language governing permissions and
16
## limitations under the License.
17
## ----------------------------------------------------------------------
18
 
19
## Based on the juvb11.pl script v1.09 by Jim McGrath, Cadence which was uploaded as UVMWorld contribution on 16 September 2011
20
## 19/02/2014  Author Christoph Suehnel, Doulos
21
## 24/02/2014  David Long, Doulos - DUT port list, auto instantiation in top
22
## 12/03/2014  David Long, Doulos - Support for multiple IFs/register sub-blocks
23
## 04/04/2014  David Long, Doulos - Naming conventions and use of config_db updated
24
## 11/04/2014  David Long, Doulos - Constraints added to seq_item
25
## 20/05/2014  David Long, Doulos - Support for multiple agents within envs. Simplified directory structure,
26
## 05/06/2014  David Long, Doulos - Revised template file format and options. Preliminary version for public release
27
## 01/09/2014  David Long, Doulos - DUT now in test harness module. Removed unnecessary child environments. Improvements to code formatting
28
## 21/09/2014  David Long, Doulos - trans_var allows typedef. item replaced by req. Added checks/coverage_enable.
29
## 08/10/2014  David Long, Doulos - fixed some naming conventions. Check "is_active"
30
## 13/10/2014  David Long, Doulos - fixed bug with "uvm_seqr_class" switch in template file
31
## 13/10/2014  David Long, Doulos - default_sequence class now derived directly from uvm_sequence
32
## 17/10/2014  David Long, Doulos - removed unnecessary base class for test. Configuration for top env now set in TB module
33
## 22/10/2014  David Long, Doulos - Top-level sequence now started by env (default test run_phase does nothing). Removed unnecessary task wait_end_test.
34
##                                  Added checking for critical warnings re include files (can be ignored by adding -c ("continue") flag to command line
35
## 06/11/2014  David Long, Doulos - Option to add common package for parameters, etc that can be accessed in all generated files (including test harness)
36
## 05/11/2014  David Long, Doulos - Generated packages now include files directly (removed .svh files). Removed unused *_common.sv files
37
## 07/11/2014  David Long, Doulos - Removed <test>_common_pkg include file - these items are now written to test common package directly.
38
##                                  Test common package file is not regenerated if it has been modified since it was created (i.e. user changes are preserved).
39
## 07/11/2014  David Long, Doulos - Top-level sequence uses UVM 1.2 API to raise/drop objections in pre/post-start.
40
## 17/11/2014  David Long, Doulos - Corrected minor formatting issues.
41
## 16/12/2014  John Aynsley, Doulos - Tidied up positioning of blank lines.
42
## 19/12/2014  John Aynsley, Doulos - Add m_ prefix to member variables. Add some pretty-printing
43
## 05/01/2015  John Aynsley, Doulos - Fix bug with properties leaking between agents
44
## 16/01/2015  John Aynsley, Doulos - Tweak formatting
45
## 20/01/2015  John Aynsley, Doulos - Tweak formatting
46
## 28/01/2015  John Aynsley, Doulos - Add a parameter regmodel_file to reg.tpl to replace the hardwired "regmodel.sv"
47
## 28/01/2015  John Aynsley, Doulos - Allow regmodel_ as well as rm_ in reg.tpl file
48
## 29/01/2015  John Aynsley, Doulos - Call `uvm_error if randomize fails
49
## 04/02/2015  John Aynsley, Doulos - Fix bug so that common package gets included in agent interfaces, rationalize package imports
50
## 04/02/2015  John Aynsley, Doulos - Allow named constraints as trans_var = values
51
## 19/02/2015  John Aynsley, Doulos - Label coverpoints using field name rather than number
52
## 19/02/2015  John Aynsley, Doulos - Add new include files inside/after classes
53
## 07/04/2015  John Aynsley, Doulos - Add new include file inside th module
54
## 21/04/2015  John Aynsley, Doulos - Generate get/set_starting_phase methods for all sequences
55
## 05/05/2015  John Aynsley, Doulos - Add several new include files and independent flags to suppress the generation of default members and methods
56
## 06/05/2015  John Aynsley, Doulos - Add ability to inline all user-defined include files
57
## 11/05/2015  John Aynsley, Doulos - Restructure <top>_common_pkg as per common_pkg (not backward-compatible)
58
## 12/05/2015  John Aynsley, Doulos - Add _prepend_to_ and _append_to_ include files for build_phase, connect_phase, run_phase methods
59
## 12/05/2015  John Aynsley, Doulos - Don't generate end_of_elaboration_phase, start_of_simulation_phase, check_phase (allows it to be user-defined more conveniently)
60
## 12/05/2015  John Aynsley, Doulos - Don't generate empty run_phase for test (allows it to be user-defined more conveniently)
61
## 19/05/2015  John Aynsley, Doulos - Support multiple instances of each interface (with _N suffix in pinlist file)
62
## 20/05/2015  John Aynsley, Doulos - Refactor all the pretty-print code
63
## 26/05/2015  John Aynsley, Doulos - Generate comments showing possible include locations
64
## 30/05/2015  John Aynsley, Doulos - Permit trans_item name clashes across agents by distinguishing the filenames
65
## 05/06/2015  John Aynsley, Doulos - Add agent_copy_config_vars
66
## 16/06/2015  John Aynsley, Doulos - Add -m command line argument to specify path to common template file. Interface template files may have any name (not just *.tpl)
67
## 16/06/2015  John Aynsley, Doulos - Add prefix = setting to common template file as alternative to -p switch
68
## 17/06/2015  John Aynsley, Doulos - Refactor by adding warning_prompt
69
## 20/06/2015  John Aynsley, Doulos - Add reg_access_mode, reg_access_map, reg_access_block_type, reg_access_block_instance, top_reg_block_type, regmodel_file
70
## 20/06/2015  John Aynsley, Doulos - Make reg.tpl optional
71
## 21/06/2015  John Aynsley, Doulos - Add top_env_generate_end_of_elaboration (default yes)
72
## 21/06/2015  John Aynsley, Doulos - Revamp messages printed from script
73
## 21/06/2015  John Aynsley, Doulos - Fix bug in gen_env which was repeating additional agent declaration in number_of_instances loop
74
## 21/06/2015  John Aynsley, Doulos - Add compile/run script for Riviera
75
## 30/09/2015  John Aynsley, Doulos - Add command line flag -x to output dut_source_path, inc_path, and project without generating any code
76
## 01/10/2015  John Aynsley, Doulos - Adjust compile_vcs.do and compile_ius.do scripts to use built-in versions of UVM-1.2
77
## 01/10/2015  John Aynsley, Doulos - Replace factory with uvm_factory::get().
78
## 20/10/2015  John Aynsley, Doulos - Make the -r switch optional: instantiation of the register model will be forced in the presence of top_reg_block_type
79
## 20/10/2015  John Aynsley, Doulos - Extend command line flag -x to output regmodel_file without generating any code
80
## 22/10/2015  John Aynsley, Doulos - Make files.f optional. If absent, create a files.f that lists just the *.sv files in the DUT directory (alphabetical order)
81
## 23/10/2015  John Aynsley, Doulos - Allow dut_source_path to default to dut, inc_path to default to include, dut_pfile to default to pinlist
82
## 23/10/2015  John Aynsley, Doulos - Add common template setting uvm_cmdline = , and remove +UVM_VERBOSITY=FULL from sim scripts, using $uvm_cmdline instead
83
## 26/10/2015  John Aynsley, Doulos - With -x regmodel_file, force the script to read reg.tpl if the file exists
84
## 03/11/2015  John Aynsley, Doulos - Moved _N suffix to before standard suffix for consistency, e.g. changed m_${agent}_agent${suffix} to m_${agent}${suffix}_agent
85
## 09/11/2015  John Aynsley, Doulos - Call comparer.compare_field in overridden do_compare method of uvm_sequence_item (to keep Syosil scoreboard happy)
86
## 16/11/2015  John Aynsley, Doulos - Add top_default_seq_count in common template
87
## 17/11/2015  John Aynsley, Doulos - Rewrite the pretty-printing code
88
## 17/11/2015  John Aynsley, Doulos - Add support for the Syosil Versatile Scoreboard: syosil_scoreboard_src_path, ref_model_input, ref_model_output
89
##                                                                                     ref_model_compare_method, ref_model_inc_before/inside/after_class
90
## 26/11/2015  John Aynsley, Doulos - Generate pack and unpack methods in uvm_sequence_item class unless cmdline flag -nopack is present for backward compatibility
91
## 26/11/2015  John Aynsley, Doulos - Add trans_enum_var setting to distinguish enum variables in do_pack, do_unpack, and convert2string - mandatory for enums in pack!
92
## 26/11/2015  John Aynsley, Doulos - Add trans_meta setting to distinguish transaction metadata and thus exclude it from do_compare, do_pack, and do_unpack methods
93
## 26/11/2015  John Aynsley, Doulos - Add trans_enum_meta for metadata that happens to be of enum type
94
## 27/11/2015  John Aynsley, Doulos - Allow single unpacked array dimension in trans_var declaration
95
## 17/12/2015  John Aynsley, Doulos - Minor cosmetic surgery on the source code
96
## 18/12/2015  John Aynsley, Doulos - Eliminated the <agent>_env directory and the <agent>_env_pkg. There is now only an <agent>_pkg.
97
##                                    Now only 1 pkg per UVC. Also scrapped subs gen_regmodel_pkg and gen_regmodel_env
98
## 19/12/2015  John Aynsley, Doulos - Made coverage object available to both coverage subscribers (agent and register), which also now contain a build_phase method
99
## 19/12/2015  John Aynsley, Doulos - Use coverage_enable to condition the calling of sample(), not the instantiation of a subscriber for an agent
100
## 19/12/2015  John Aynsley, Doulos - Move code executed after parsing control files to separate subs
101
## 20/12/2015  John Aynsley, Doulos - Removed the unused dut_inc_path and inc_file code
102
## 23/12/2015  John Aynsley, Doulos - Permit / in include filenames so that ./include can be structured into subdirectories
103
## 11/01/2016  John Aynsley, Doulos - Permit trans_var/trans_meta = // SystemVerilog comment
104
## 20/01/2016  John Aynsley, Doulos - Insert agent_copy_config_vars inc file only once if number_of_instances > 1, which can thus copy vars for multiple config objects
105
## 21/01/2016  John Aynsley, Doulos - Add dual_top and split_transactors to support acceleration/emulation-ready environments
106
## 01/02/2016  John Aynsley, Doulos - Add timeunit and timeprecision to interfaces (was previously only inserted in modules)
107
## 15/02/2016  John Aynsley, Doulos - Fix bug related to print_structure - %env_agents needs to store a copy of @additional_agents, not a \reference
108
## 15/02/2016  John Aynsley, Doulos - Add top_env_generate_run_phase (default yes)
109
## 15/02/2016  John Aynsley, Doulos - Add generate_file_header and file_header_inc
110
## 15/02/2016  John Aynsley, Doulos - Clean up auto-generated file header to only write out lines that are defined
111
## 17/02/2016  John Aynsley, Doulos - Add adapter_generate_methods_inside/after_class and adapter_inc_before/inside/after class
112
## 18/02/2016  John Aynsley, Doulos - Add nested_config_objects
113
## 18/02/2016  John Aynsley, Doulos - Add top_env_config_append_to_new
114
## 18/02/2016  John Aynsley, Doulos - Add top_env_config_generate_methods_inside/after_class
115
## 18/02/2016  John Aynsley, Doulos - Add agent_config_generate_methods_inside/after_class
116
## 18/02/2016  John Aynsley, Doulos - Add tb_generate_run_test
117
## 08/03/2016  John Aynsley, Doulos - Add -s command line switch to override syosil_scoreboard_src_path setting in common template
118
## 31/03/2016  John Aynsley, Doulos - Permit end-of-line comment with DEC in pinlist file
119
## 31/03/2016  John Aynsley, Doulos - Fix bug with trailing comments after last port connection in pinlist file
120
## 31/03/2016  John Aynsley, Doulos - Add calls to .set_item_context() before randomizing sequence objects to ensure random stability
121
## 05/04/2016  John Aynsley, Doulos - Replace -f with -F in Riviera script
122
## 06/04/2016  John Aynsley, Doulos - Modify compile_riviera.do script to compile everything UVM with a single call to alog
123
## 15/04/2016  John Aynsley, Doulos - Add tb_prepend_to_initial and tb_inc_before_run_test
124
## 15/04/2016  John Aynsley, Doulos - Add generate_interface_instance = no (interface instance not generated and vif not assigned)
125
## 15/04/2016  John Aynsley, Doulos - Add byo_interface
126
## 15/04/2016  John Aynsley, Doulos - Allow user-defined interface instance names in the pinlist file
127
## 15/04/2016  John Aynsley, Doulos - Changed "virtual interface is not set!" report from FATAL to WARNING - because might have a parameterized interface
128
## 12/05/2016  John Aynsley, Doulos - Allow multiple +uvm_cmdline settings to apply additively
129
## 27/05/2016  John Aynsley, Doulos - Don't generate empty build_phase method for monitor
130
## 27/05/2016  John Aynsley, Doulos - Modify compile_riviera.do script to use the UVM 1.2 library supplied with Riviera
131
## 11/08/2016  John Aynsley, Doulos - Fix serious bug - the default env sequence was not being started for an agent that accessed a register model
132
## 05/10/2016  John Aynsley, Doulos - Don't use the monitor's analysis port outside of the agent. Use the agent's analysis port instead.
133
## 07/10/2016  John Aynsley, Doulos - Move assignment to m_item in function <agent>_coverage::write
134
## 07/10/2016  John Aynsley, Doulos - Move lines around in generated code for top_default_sequence 
135
## 07/10/2016  John Aynsley, Doulos - Add an m_config member to every ${agent_name}_env_default_seq register sequence and assign before start
136
## 10/10/2016  John Aynsley, Doulos - Add an m_config member to every ${agent_name}_default_seq and assign before start
137
## 10/10/2016  John Aynsley, Doulos - Add an m_config member to every driver and monitor and assign in agent::connect
138
 
139
 
140
## Easier UVM Generator
141
 
142
use strict;
143
use warnings;
144
require 5.8.0;
145
 
146
use File::Copy::Recursive qw(dircopy);
147
use File::Copy "cp";
148
use File::stat;
149
 
150
my $VERNUM = "2017-01-19";
151
 
152
# Subroutine prototypes:
153
sub  parse_cmdline;
154
sub  usage;
155
sub  parse_common;
156
sub  after_parse_common;
157
sub  parse_reg_template;
158
sub  parse_template;
159
sub  after_parse_template;
160
sub  check_file;
161
sub  check_inc_file;
162
sub  check_common_pkg;
163
sub  check_common_env_pkg;
164
sub  gen_bfm;
165
sub  gen_if;
166
sub  gen_seq_item;
167
sub  gen_driver;
168
sub  gen_monitor;
169
sub  gen_sequencer;
170
sub  gen_config;
171
sub  gen_cov;
172
sub  gen_agent;
173
sub  gen_env;
174
sub  gen_seq_lib;
175
sub  gen_env_seq_lib;
176
sub  gen_agent_pkg;
177
sub  gen_top_pkg;
178
sub  gen_dut_inst;
179
sub  gen_top;
180
sub  gen_port_converter;
181
sub  gen_ref_model;
182
sub  gen_top_env;
183
sub  gen_top_config;
184
sub  gen_top_seq_lib;
185
sub  gen_top_test;
186
sub  gen_regmodel_adapter;
187
sub  gen_regmodel_coverage;
188
sub  gen_regmodel_seq_lib;
189
sub  gen_questa_script;
190
sub  gen_vcs_script;
191
sub  gen_ius_script;
192
sub  gen_riviera_script;
193
sub  gen_compile_file_list;
194
sub  get_pkg_name;
195
sub  write_file_header;
196
 
197
 
198
# Scalar Variables:
199
my $agent_has_env;
200
my $agent_if;
201
my $agent_item;
202
my $agent_name;
203
my $agent_reset;
204
my $agent_seqr_class;
205
my $aname;
206
my $argnum;
207
my $author;
208
my $backup;
209
my $common_pkg;
210
my $common_pkg_fname;
211
my $common_env_pkg;
212
my $common_env_pkg_fname;
213
my $common_tpl_fname;
214
my $company;
215
my $continue_on_warning;
216
my $copyright;
217
my $date;
218
my $dept;
219
my $dir1;
220
my $dir2;
221
my $dir;
222
my $dual_top;
223
my $dut_iname;
224
my $dut_path;
225
my $dut_pfile;
226
my $dut_tb_dir;
227
my $dut_tb_path;
228
my $dut_top;
229
my $ele;
230
my $email;
231
my $env_clock_list;
232
my $env_reset_list;
233
my $field;
234
my $file_header_inc;
235
my $flag_dut_source_path;
236
my $flag_inc_path;
237
my $flag_project;
238
my $flag_regmodel_file;
239
my $flag_x;
240
my $flag_nopack;
241
my $comments_at_include_locations;
242
my $generate_file_header;
243
my $nested_config_objects;
244
my $i;
245
my $inc_file;
246
my $inc_path;
247
my $incdir;
248
my $name;
249
my $pf;
250
my $port_decl;
251
my $project;
252
my $reg_template;
253
my $regmodel;
254
my $regmodel_file;
255
my $split_transactors;
256
my $syosil_scoreboard_src_path;
257
my $top_reg_block_type;
258
my $tbname;
259
my $tb_inc_before_run_test;
260
my $tb_inc_before_run_test_inline;
261
my $tb_inc_inside_module;
262
my $tb_inc_inside_inline;
263
my $tb_generate_run_test;
264
my $tb_module_name;
265
my $tb_prepend_to_initial;
266
my $tb_prepend_to_initial_inline;
267
my $th_module_name;
268
my $tel;
269
my $template_list;
270
my $template_name;
271
my $th_generate_clock_and_reset;
272
my $th_inc_inside_module;
273
my $th_inc_inside_inline;
274
my $timeunit;
275
my $timeprecision;
276
my $test_generate_methods_inside_class;
277
my $test_generate_methods_after_class;
278
my $test_inc_before_class;
279
my $test_inc_before_inline;
280
my $test_inc_inside_class;
281
my $test_inc_inside_inline;
282
my $test_inc_after_class;
283
my $test_inc_after_inline;
284
my $test_prepend_to_build_phase;
285
my $test_prepend_to_build_phase_inline;
286
my $test_append_to_build_phase;
287
my $test_append_to_build_phase_inline;
288
my $top_env_config_append_to_new;
289
my $top_env_config_append_to_new_inline;
290
my $top_env_config_generate_methods_inside_class;
291
my $top_env_config_generate_methods_after_class;
292
my $top_default_seq_count;
293
my $top_env_config_inc_before_class;
294
my $top_env_config_inc_before_inline;
295
my $top_env_config_inc_inside_class;
296
my $top_env_config_inc_inside_inline;
297
my $top_env_config_inc_after_class;
298
my $top_env_config_inc_after_inline;
299
my $top_env_generate_methods_inside_class;
300
my $top_env_generate_methods_after_class;
301
my $top_env_generate_end_of_elaboration;
302
my $top_env_generate_run_phase;
303
my $top_env_inc_before_class;
304
my $top_env_inc_before_inline;
305
my $top_env_inc_inside_class;
306
my $top_env_inc_inside_inline;
307
my $top_env_inc_after_class;
308
my $top_env_inc_after_inline;
309
my $top_env_prepend_to_build_phase;
310
my $top_env_prepend_to_build_phase_inline;
311
my $top_env_append_to_build_phase;
312
my $top_env_append_to_build_phase_inline;
313
my $top_env_append_to_connect_phase;
314
my $top_env_append_to_connect_phase_inline;
315
my $top_env_append_to_run_phase;
316
my $top_env_append_to_run_phase_inline;
317
my $top_seq_inc;
318
my $top_seq_inc_inline;
319
my $uvm_cmdline;
320
my $uvm_reg_addr;
321
my $uvm_reg_data;
322
my $uvm_reg_kind;
323
my $var_decl;
324
my $year;
325
my $version;
326
 
327
# Hash Variables
328
my %agent_adapter_generate_methods_inside_class;
329
my %agent_adapter_generate_methods_after_class;
330
my %agent_adapter_inc_before_class;
331
my %agent_adapter_inc_before_inline;
332
my %agent_adapter_inc_inside_class;
333
my %agent_adapter_inc_inside_inline;
334
my %agent_adapter_inc_after_class;
335
my %agent_adapter_inc_after_inline;
336
my %agent_append_to_build_phase;
337
my %agent_append_to_build_phase_inline;
338
my %agent_append_to_connect_phase;
339
my %agent_append_to_connect_phase_inline;
340
my %agent_checks_enable;
341
my %agent_config_generate_methods_inside_class;
342
my %agent_config_generate_methods_after_class;
343
my %agent_config_inc_before_class;
344
my %agent_config_inc_before_inline;
345
my %agent_config_inc_inside_class;
346
my %agent_config_inc_inside_inline;
347
my %agent_config_inc_after_class;
348
my %agent_config_inc_after_inline;
349
my %agent_copy_config_vars;
350
my %agent_copy_config_vars_inline;
351
my %agent_cover_generate_methods_inside_class;
352
my %agent_cover_generate_methods_after_class;
353
my %agent_cover_inc;
354
my %agent_cover_inc_inline;
355
my %agent_cover_inc_before_class;
356
my %agent_cover_inc_before_inline;
357
my %agent_cover_inc_inside_class;
358
my %agent_cover_inc_inside_inline;
359
my %agent_cover_inc_after_class;
360
my %agent_cover_inc_after_inline;
361
my %agent_coverage_enable;
362
my %agent_driv_inc;
363
my %agent_driv_inc_inline;
364
my %agent_driv_inc_before_class;
365
my %agent_driv_inc_before_inline;
366
my %agent_driv_inc_inside_class;
367
my %agent_driv_inc_inside_inline;
368
my %agent_driv_inc_after_class;
369
my %agent_driv_inc_after_inline;
370
my %agent_env_prepend_to_build_phase;
371
my %agent_env_prepend_to_build_phase_inline;
372
my %agent_env_append_to_build_phase;
373
my %agent_env_append_to_build_phase_inline;
374
my %agent_env_append_to_connect_phase;
375
my %agent_env_append_to_connect_phase_inline;
376
my %agent_env_generate_methods_inside_class;
377
my %agent_env_generate_methods_after_class;
378
my %agent_env_inc_before_class;
379
my %agent_env_inc_before_inline;
380
my %agent_env_inc_inside_class;
381
my %agent_env_inc_inside_inline;
382
my %agent_env_inc_after_class;
383
my %agent_env_inc_after_inline;
384
my %agent_env_seq_inc;
385
my %agent_env_seq_inc_inline;
386
my %agent_factory_set;
387
my %agent_generate_methods_inside_class;
388
my %agent_generate_methods_after_class;
389
my %agent_is_active;
390
my %agent_inc_before_class;
391
my %agent_inc_before_inline;
392
my %agent_inc_inside_class;
393
my %agent_inc_inside_inline;
394
my %agent_inc_after_class;
395
my %agent_inc_after_inline;
396
my %agent_inc_inside_bfm;
397
my %agent_inc_inside_bfm_inline;
398
my %agent_mon_inc;
399
my %agent_mon_inc_inline;
400
my %agent_mon_inc_before_class;
401
my %agent_mon_inc_before_inline;
402
my %agent_mon_inc_inside_class;
403
my %agent_mon_inc_inside_inline;
404
my %agent_mon_inc_after_class;
405
my %agent_mon_inc_after_inline;
406
my %agent_parent;
407
my %agent_prepend_to_build_phase;
408
my %agent_prepend_to_build_phase_inline;
409
my %agent_seq_inc;
410
my %agent_seq_inc_inline;
411
my %agent_seqr_inc_before_class;
412
my %agent_seqr_inc_before_inline;
413
my %agent_seqr_inc_inside_class;
414
my %agent_seqr_inc_inside_inline;
415
my %agent_seqr_inc_after_class;
416
my %agent_seqr_inc_after_inline;
417
my %agent_item_types;
418
my %agent_trans_generate_methods_inside_class;
419
my %agent_trans_generate_methods_after_class;
420
my %agent_trans_inc_before_class;
421
my %agent_trans_inc_before_inline;
422
my %agent_trans_inc_inside_class;
423
my %agent_trans_inc_inside_inline;
424
my %agent_trans_inc_after_class;
425
my %agent_trans_inc_after_inline;
426
my %agent_type_by_inst;
427
my %bus2reg_map;
428
my %byo_interface;
429
my %enum_var_types;
430
my %env_agents;
431
my %generate_interface_instance;
432
my %if_inc_inside_interface;
433
my %if_inc_inside_inline;
434
my %if_instance_names;    # Used to identify instances in the dut_pfile (the pinlist)
435
my %number_of_instances;  # Number of instances required of each agent/interface
436
my %reg_access_block_type;      # Type of uvm_reg_block class containing registers
437
my %reg_access_instance;  # Object path of uvm_reg_block class containing registers, appended to regmodel. Should be an empty string or start with a dot
438
my %reg_access_map;       # Instance of map within uvm_reg_block
439
my %reg_access_mode;      # Register access mode WR WO RO
440
my %reg_cover_generate_methods_inside_class;
441
my %reg_cover_generate_methods_after_class;
442
my %reg_cover_inc;
443
my %reg_cover_inc_inline;
444
my %reg_cover_inc_before_class;
445
my %reg_cover_inc_before_inline;
446
my %reg_cover_inc_inside_class;
447
my %reg_cover_inc_inside_inline;
448
my %reg_cover_inc_after_class;
449
my %reg_cover_inc_after_inline;
450
my %ref_model;
451
my %ref_model_inputs;
452
my %ref_model_outputs;
453
my %ref_model_compare_method;
454
my %ref_model_inc_before_class;
455
my %ref_model_inc_before_inline;
456
my %ref_model_inc_inside_class;
457
my %ref_model_inc_inside_inline;
458
my %ref_model_inc_after_class;
459
my %ref_model_inc_after_inline;
460
my %top_factory_set;
461
my %tpl_fname;
462
my %unpacked_bound;
463
 
464
# Array Variables
465
my @additional_agents;
466
my @agent_clock_array;
467
my @agent_instance_names;
468
my @agent_list;      # Array of all agent names
469
my @agent_port_array;
470
my @agent_reset_array;
471
my @agent_var_array;
472
my @agent_enum_array;
473
my @agent_meta_array;
474
my @agent_var_cnstr_array;
475
my @all_agent_ifs;   # Array of all interface names, including the _if suffix (not the interface instance names)
476
my @clist;
477
my @common_config_var_array;
478
my @config_var_array;
479
my @elist;
480
my @env_list;
481
my @fields;
482
my @inc_path_list;
483
my @list;
484
my @all_tx_vars;
485
my @non_local_tx_vars;
486
my @non_meta_tx_vars;
487
my @non_reg_env;
488
my @reg_env;
489
my @rlist;
490
my @stand_alone_agents;
491
my @top_env_agents;
492
 
493
 
494
open( LOGFILE, ">easier_uvm_gen.log" );
495
print LOGFILE "\nEasier UVM Code Generator version ${VERNUM}"
496
  . " (Send feedback to info\@doulos.com)\n";
497
 
498
set_default_values();
499
parse_cmdline();
500
parse_common();
501
after_parse_common();
502
deal_with_deprecated_reg_template();
503
handle_minus_x_flag();
504
 
505
#Only print this message after calling handle_minus_x_flag() in case handle_minus_x_flag() prints out one of the paths and exits the script
506
print "Easier UVM Code Generator version ${VERNUM}\n";
507
 
508
check_common_pkg($common_pkg_fname) if $common_pkg_fname;
509
check_common_env_pkg($common_env_pkg_fname) if $common_env_pkg_fname;
510
 
511
create_directories_and_copy_files();
512
 
513
# Process the agent templates (@list created by parse_cmdline)
514
print LOGFILE "\nParsing Templates ...\n\n";
515
foreach my $i ( 0 .. @list - 1) {
516
    if ( $list[$i] ne "" ) {
517
        $template_name = $list[$i];
518
        printf LOGFILE "Reading[$i]: $list[$i]\n";
519
 
520
        parse_template();
521
        after_parse_template();
522
 
523
        # Make the per-agent directories
524
        $dir = "${project}/tb/${agent_name}";
525
        printf LOGFILE "dir: $dir\n";
526
        mkdir( $dir,         0755 );
527
        mkdir( $dir . "/sv", 0755 );
528
        print LOGFILE "Writing code to files\n";
529
 
530
        # Create the agent files
531
        gen_if();
532
        if ( $split_transactors eq "YES") {
533
          gen_bfm();
534
        }
535
        gen_seq_item();
536
        gen_config();
537
        gen_driver();
538
        gen_monitor();
539
        gen_sequencer();
540
        gen_cov();
541
        gen_agent();
542
        gen_seq_lib();
543
 
544
        # Do not generate env or env_seq_lib if regmodel used or $agent_has_env = no
545
        do {
546
            gen_env();
547
            gen_env_seq_lib();
548
        } unless ( exists $reg_access_mode{$agent_name} ) or $agent_has_env eq "NO";
549
 
550
        gen_agent_pkg();
551
    }
552
}
553
if ( $regmodel eq 1 ) {
554
    gen_regmodel_pkg();
555
 
556
    foreach my $agent ( keys(%reg_access_mode) ) {
557
        $agent_name = $agent;
558
        gen_env();
559
        gen_regmodel_adapter();
560
        gen_regmodel_coverage();
561
        gen_regmodel_seq_lib();
562
    }
563
}
564
 
565
extra_checking_for_additional_agents();
566
 
567
print LOGFILE "top env agents = @top_env_agents\n";
568
print LOGFILE "Generating testbench in ${project}/tb\n";
569
print "Generating testbench in         ${project}/tb\n";
570
 
571
gen_top_config();
572
gen_port_converter();
573
 
574
foreach my $ref_model_name ( keys(%ref_model) ) {
575
    gen_ref_model($ref_model_name);
576
}
577
 
578
gen_top_env();
579
gen_top_seq_lib();
580
gen_top_pkg();
581
gen_top_test();
582
gen_top();
583
 
584
print "Generating simulator scripts in ${project}/sim\n";
585
print LOGFILE "Generating simulator scripts in ${project}/sim\n";
586
 
587
deal_with_files_f();
588
 
589
gen_questa_script();
590
gen_vcs_script();
591
gen_ius_script();
592
gen_riviera_script();
593
 
594
print_structure();
595
 
596
print LOGFILE "Code Generation complete\n";
597
 
598
 
599
# ---------- Subroutines -------------------------------------------------
600
 
601
sub set_default_values {
602
 
603
    $date       = localtime;
604
    $project    = "generated_tb";
605
    $backup     = "yes";
606
    $version    = "1.0";
607
    $inc_path   = "include";
608
    $inc_file   = "";
609
    $dut_path   = "dut";
610
    $common_pkg = "";
611
    $common_pkg_fname     = "";
612
    $common_env_pkg       = "";
613
    $common_env_pkg_fname = "";
614
    $common_tpl_fname     = "common.tpl";
615
 
616
    $agent_name     = "";
617
    $agent_if       = "";
618
    $agent_item     = "";
619
    $dut_iname      = "uut";    #instance name of dut in tb
620
    $timeunit       = "1ns";
621
    $timeprecision  = "1ps";
622
    $regmodel       = 0;
623
    $dut_top        = "";          #top level dut module
624
    $dut_pfile      = "pinlist";   #dut port list file
625
    $uvm_cmdline    = "";
626
    $top_default_seq_count = undef;
627
 
628
    $env_reset_list = "";
629
    $env_clock_list = "";
630
    $tbname         = undef;
631
 
632
    $regmodel_file  = "regmodel.sv";
633
    $top_reg_block_type  = undef;
634
 
635
    $syosil_scoreboard_src_path = undef;
636
 
637
    $template_name  = "example.tpl";    #default template name
638
    $template_list  = "";               #default template list
639
    $reg_template   = undef;
640
 
641
    $dual_top          = "NO";
642
    $split_transactors = "NO";
643
}
644
 
645
sub parse_cmdline {
646
    print LOGFILE "\nParsing cmdline ...\n\n";
647
    print LOGFILE "num args is " . $#ARGV . "\n";
648
    if ( $#ARGV == -1 ) { usage(); }    ### no arguments, print help and exit
649
    ###if ($ARGV[$argnum] =~ m/\s*help/i)
650
    if ( $ARGV[0] =~ m/\s*(-help|-hel|-he|-h)/i ) {
651
        usage();
652
    }
653
    my $pnum_c = -2;
654
    my $pnum_r = -2;
655
    my $pnum_p = -2;
656
    my $pnum_m = -2;
657
    my $pnum_s = -2;
658
    my $pnum_n = -2;
659
    $continue_on_warning = 0;
660
 
661
    # Searching for -x dut_source_path, -x inc_path, and -x project flag
662
    foreach $argnum ( 0 .. $#ARGV) {
663
        if ( $ARGV[$argnum] =~ m/\s*(-x)/i ) {
664
            if ( $ARGV[ $argnum + 1 ] eq "dut_source_path" ) {
665
                $flag_x = 1;
666
                $flag_dut_source_path = 1;
667
            }
668
            if ( $ARGV[ $argnum + 1 ] eq "inc_path" ) {
669
                $flag_x = 1;
670
                $flag_inc_path = 1;
671
            }
672
            if ( $ARGV[ $argnum + 1 ] eq "project" ) {
673
                $flag_x = 1;
674
                $flag_project = 1;
675
            }
676
            if ( $ARGV[ $argnum + 1 ] eq "regmodel_file" ) {
677
                $flag_x = 1;
678
                $flag_regmodel_file = 1;
679
            }
680
        }
681
    }
682
 
683
    # Searching for "continue on critical warnings" flag
684
    foreach $argnum ( 0 .. $#ARGV) {
685
        if ( $ARGV[$argnum] =~ m/\s*(-c)/i ) {
686
            $pnum_c = $argnum;
687
            $continue_on_warning = 1;
688
            printf LOGFILE "Code generation will continue if critical warnings are issued\n";
689
            printf LOGFILE "pnum_c: $pnum_c\n";
690
        }
691
    }
692
 
693
    # Searching for register flag
694
    printf LOGFILE "Searching for regmodel flag\n";
695
    foreach $argnum ( 0 .. $#ARGV) {
696
        if ( $ARGV[$argnum] =~ m/\s*(-r)/i ) {
697
            $regmodel = 1;
698
            $pnum_r   = $argnum;
699
            printf LOGFILE
700
              "regmodel: $regmodel, Register layer will be included\n";
701
            printf LOGFILE "pnum_r: $pnum_r\n";
702
        }
703
    }
704
 
705
    # Searching for project name
706
    printf LOGFILE "Searching for prefix\n";
707
    foreach $argnum ( 0 .. $#ARGV) {
708
        if ( $ARGV[$argnum] =~ m/\s*(-p)/i ) {
709
            $tbname = $ARGV[ $argnum + 1 ];
710
            $pnum_p = $argnum;
711
            printf LOGFILE "prefix: $tbname\n";
712
            printf LOGFILE "pnum_p: $pnum_p\n";
713
        }
714
    }
715
 
716
    # Searching for common template filename
717
    printf LOGFILE "Searching for common template\n";
718
    foreach $argnum ( 0 .. $#ARGV) {
719
        if ( $ARGV[$argnum] =~ m/\s*(-m)/i ) {
720
            $common_tpl_fname = $ARGV[ $argnum + 1 ];
721
            $pnum_m  = $argnum;
722
            printf LOGFILE "common_tpl_fname: $common_tpl_fname\n";
723
            printf LOGFILE "pnum_m: $pnum_m\n";
724
        }
725
 
726
    }
727
 
728
    # Searching for Syosil scoreboard path
729
    printf LOGFILE "Searching for Syosil scoreboard path\n";
730
    foreach $argnum ( 0 .. $#ARGV) {
731
        if ( $ARGV[$argnum] =~ m/\s*(-s)/i ) {
732
            $syosil_scoreboard_src_path = $ARGV[ $argnum + 1 ];
733
            $pnum_s = $argnum;
734
            printf LOGFILE "syosil_scoreboard_src_path: $syosil_scoreboard_src_path\n";
735
            printf LOGFILE "pnum_s: $pnum_s\n";
736
        }
737
    }
738
 
739
    # Searching for -nopack flag
740
    foreach $argnum ( 0 .. $#ARGV) {
741
        if ( $ARGV[$argnum] =~ m/\s*(-nopack)/i ) {
742
            $flag_nopack = 1;
743
            $pnum_n = $argnum;
744
        }
745
    }
746
 
747
    # searching for template (agent) names
748
    printf LOGFILE "Searching for templates\n";
749
    foreach $argnum ( 0 .. $#ARGV) {
750
 
751
        if ( $argnum != $pnum_c &&
752
             $argnum != $pnum_r &&
753
             $argnum != $pnum_p && $argnum != $pnum_p + 1 &&
754
             $argnum != $pnum_m && $argnum != $pnum_m + 1 &&
755
             $argnum != $pnum_s && $argnum != $pnum_s + 1 &&
756
             $argnum != $pnum_n ) {
757
 
758
            #check for template name
759
            if ( $ARGV[$argnum] =~
760
                m/\s*(-template|-templat|-templa|-templ|-tem|-te|-t)/i )
761
            {
762
                print LOGFILE "template: $ARGV[$argnum]\n";
763
            }
764
            else {
765
                if ( $ARGV[$argnum] ne "reg.tpl" ) {
766
                    $template_list = "$template_list $ARGV[$argnum]";
767
 
768
                    #print LOGFILE "T_List: $template_list\n";
769
                }
770
                else {
771
                    $reg_template = $ARGV[$argnum];
772
                }
773
            }
774
 
775
            print LOGFILE "T_List: $template_list\n";
776
            if ( $ARGV[$argnum] =~ m/\s*(-help|-hel|-he|-h)/i ) {
777
                usage();
778
            }
779
        }
780
        @list = split /\s+/, $template_list;
781
        foreach $i ( 0 .. @list-1 ) {
782
            if ( $list[$i] ne "" ) {
783
                printf LOGFILE "List: $list[$i]\n";
784
            }
785
        }
786
    }
787
    @list or die "ERROR! You must specify at least 1 template file)\n";
788
}
789
 
790
sub usage {
791
    print "\n";
792
    print "USAGE: perl easier_uvm_gen.pl [-t] <filename> <filename> ...     list of template file names\n";
793
    print "\n";
794
    print "       -p <top>            Prefix used to construct names associated with top-level env, default is top\n";
795
    print "       -m <filename>       Path to common template file, default is common.tpl\n";
796
    print "       -s <path>           Path to source files for Syosil scoreboard (overrides syosil_scoreboard_src_path in common template)\n";
797
    print "       -c                  The code generator will continue after warnings\n";
798
    print "       -r                  Causes a register model to be instantiated in the generated code (switch is no longer necessary}\n";
799
    print "       -x dut_source_path  Returns the value of the dut_source_path setting\n";
800
    print "       -x inc_path         Returns the value of the inc_path setting\n";
801
    print "       -x project          Returns the value of the project setting\n";
802
    print "       -x regmodel_file    Returns the value of the regmodel_file setting\n";
803
    print "       -nopack             Suppresses generation of do_pack & do_unpack methods for backward compatibility\n";
804
    print "\n";
805
    exit;
806
}    # end sub usage
807
 
808
sub parse_common {
809
    my $template_name = $common_tpl_fname;
810
    @common_config_var_array   = ();
811
 
812
    open( TH, $template_name )
813
      || die "Exiting due to Error: can't open template: ${template_name}\n";
814
    print LOGFILE "Parsing common : $template_name ...\n\n";
815
 
816
    for ( ; ; ) {
817
        my $line;
818
        undef $!;
819
        unless ( defined( $line = <TH> ) ) {
820
            die $! if $!;
821
            last;    # reached EOF
822
        }
823
 
824
        next if ( $line =~ m/^\s*#/ );    #comment line starts with "#"
825
        next if ( $line =~ m/^\s+$/ );    #blank line
826
 
827
        $line =~ s/(^.*?)#.*/$1/;         #delete trailing comments
828
 
829
        $line =~ /^\s*(\w+)\s*=\s*(.+?)\s*$/
830
          or die "Exiting due to Error: bad entry in line $. of ${common_tpl_fname}: $line\n";
831
        my $param_name  = $1;
832
        my $param_value = $2;
833
 
834
        #check for dut path
835
        if ( $param_name =~ /dut_source_path/i ) {
836
            $dut_path = $param_value;
837
            print LOGFILE "dut_path: $dut_path\n";
838
        }
839
 
840
        #check for include paths
841
        if ( $param_name =~ /^\s*inc_path/i ) {
842
            $inc_path = $param_value;
843
        }
844
 
845
        #check for project
846
        if ( $param_name =~ /project/i ) {
847
            $project = $param_value;
848
            print LOGFILE "Project: $project\n";
849
        }
850
 
851
        #check for regmodel file
852
        if ( $param_name =~ /regmodel_file/i) {
853
            unless (defined($flag_x)) {
854
                    check_file($param_value);
855
            }
856
            $regmodel_file = $param_value;
857
            print LOGFILE "regmodel_file: $regmodel_file\n";
858
        }
859
 
860
        #check for top-level regmodel type
861
        if ( $param_name =~ /top_reg_block_type/i) {
862
            $top_reg_block_type = $param_value;
863
            print LOGFILE "top_reg_block_type: $top_reg_block_type\n";
864
        }
865
 
866
        # Don't parse the rest of the settings if called with the -x switch
867
        unless (defined($flag_x)) {
868
 
869
        if ( $param_name =~ /prefix/i ) {
870
            unless ( defined $tbname ) {
871
                $tbname = $param_value;
872
                print LOGFILE "Prefix: $tbname\n";
873
            }
874
        }
875
 
876
        if ( $param_name =~ /backup/i ) {
877
            $backup = uc $param_value;
878
            print LOGFILE "Backup: $backup\n";
879
        }
880
 
881
        if ( $param_name =~ /comments_at_include_locations/i ) {
882
            $comments_at_include_locations = uc $param_value;
883
            print LOGFILE "comments_at_include_locations = $comments_at_include_locations\n";
884
        }
885
 
886
        if ( $param_name =~ /copyright/i ) {
887
            $copyright = $param_value;
888
            print LOGFILE "$copyright\n";
889
        }
890
 
891
        if ( $param_name =~ /^\s*name/i ) {
892
            $author = $param_value;
893
            print LOGFILE "Name: $author\n";
894
        }
895
 
896
        if ( $param_name =~ /email/i ) {
897
            $email = $param_value;
898
            print LOGFILE "email: $email\n";
899
        }
900
 
901
        if ( $param_name =~ /tel/i ) {
902
            $tel = $param_value;
903
            print LOGFILE "Tel: $tel\n";
904
        }
905
 
906
        if ( $param_name =~ /dept/i ) {
907
            $dept = $param_value;
908
            print LOGFILE "dept: $dept\n";
909
        }
910
 
911
        if ( $param_name =~ /company/i ) {
912
            $company = $param_value;
913
            print LOGFILE "company: $dept\n";
914
        }
915
 
916
        if ( $param_name =~ /year/i ) {
917
            $year = $param_value;
918
            print LOGFILE "year: $year\n";
919
        }
920
 
921
        if ( $param_name =~ /version/i ) {
922
            $version = $param_value;
923
            print LOGFILE "version : $version\n";
924
        }
925
 
926
        if ( $param_name =~ /dut_top/i ) {
927
            $dut_top = $param_value;
928
            print LOGFILE "dut_top: $dut_top\n";
929
        }
930
 
931
        if ( $param_name =~ /dut_iname/i ) {
932
            $dut_iname = $param_value;
933
            print LOGFILE "dut instance name: $dut_iname\n";
934
        }
935
 
936
        if ( $param_name =~ /dut_pfile/i ) {
937
            $dut_pfile = $param_value;
938
            print LOGFILE "dut_pfile: $dut_pfile\n";
939
        }
940
 
941
        if ( $param_name =~ /timeunit/i ) {
942
            $timeunit = $param_value;
943
            print LOGFILE "timeunit: $timeunit\n";
944
        }
945
 
946
        if ( $param_name =~ /timeprecision/i ) {
947
            $timeprecision = $param_value;
948
            print LOGFILE "timeprecision: $timeprecision\n";
949
        }
950
 
951
        if ( $param_name =~ /uvm_cmdline/i ) {
952
            $uvm_cmdline = $uvm_cmdline ? "$uvm_cmdline $param_value" : $param_value;
953
            print LOGFILE "uvm_cmdline: $uvm_cmdline\n";
954
        }
955
 
956
        if ( $param_name =~ /nested_config_objects/i ) {
957
            $nested_config_objects = uc $param_value;
958
            print LOGFILE "nested_config_objects = $param_value\n";
959
        }
960
 
961
        if ( $param_name =~ /common_pkg/i ) {
962
            $common_pkg_fname = $param_value;
963
            print LOGFILE "common package file name: $common_pkg_fname\n";
964
        }
965
 
966
        if ( $param_name =~ /common_env_pkg/i ) {
967
            $common_env_pkg_fname = $param_value;
968
            print LOGFILE "common env package file name: $common_env_pkg_fname\n";
969
        }
970
 
971
        if ( $param_name =~ /tb_inc_inside_module/i ) {
972
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
973
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
974
              check_inc_file($1);
975
            $tb_inc_inside_module = $1;
976
            $tb_inc_inside_inline = $3 if ($3);
977
            print LOGFILE "tb_inc_inside_module = $param_value\n";
978
        }
979
 
980
        if ( $param_name =~ /tb_inc_before_run_test/i ) {
981
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
982
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
983
              check_inc_file($1);
984
            $tb_inc_before_run_test = $1;
985
            $tb_inc_before_run_test_inline = $3 if ($3);
986
            print LOGFILE "tb_inc_before_run_test = $param_value\n";
987
        }
988
 
989
        if ( $param_name =~ /tb_prepend_to_initial/i ) {
990
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
991
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
992
              check_inc_file($1);
993
            $tb_prepend_to_initial        = $1;
994
            $tb_prepend_to_initial_inline = $3 if ($3);
995
            print LOGFILE "tb_prepend_to_initial = $param_value\n";
996
        }
997
 
998
        if ( $param_name =~ /tb_generate_run_test/i ) {
999
            $tb_generate_run_test = uc $param_value;
1000
            print LOGFILE "tb_generate_run_test = $param_value\n";
1001
        }
1002
 
1003
        if ( $param_name =~ /th_generate_clock_and_reset/i ) {
1004
            $th_generate_clock_and_reset = uc $param_value;
1005
            print LOGFILE "th_generate_clock_and_reset = $param_value\n";
1006
        }
1007
 
1008
        if ( $param_name =~ /th_inc_inside_module/i ) {
1009
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1010
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1011
              check_inc_file($1);
1012
            $th_inc_inside_module = $1;
1013
            $th_inc_inside_inline = $3 if ($3);
1014
            print LOGFILE "th_inc_inside_module = $param_value\n";
1015
        }
1016
 
1017
        if ( $param_name =~ /generate_file_header/i ) {
1018
            $generate_file_header = uc $param_value;
1019
            print LOGFILE "generate_file_header = $param_value\n";
1020
        }
1021
 
1022
        if ( $param_name =~ /file_header_inc/i ) {
1023
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1024
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1025
                check_inc_file($1);
1026
            $file_header_inc = $1;
1027
            print LOGFILE "file_header_inc = $param_value\n";
1028
        }
1029
 
1030
        if ( $param_name =~ /test_generate_methods_inside_class/i ) {
1031
            $test_generate_methods_inside_class = uc $param_value;
1032
            print LOGFILE "test_generate_methods_inside_class = $param_value\n";
1033
        }
1034
 
1035
        if ( $param_name =~ /test_generate_methods_after_class/i ) {
1036
            $test_generate_methods_after_class = uc $param_value;
1037
            print LOGFILE "test_generate_methods_after_class = $param_value\n";
1038
        }
1039
 
1040
        if ( $param_name =~ /test_inc_before_class/i ) {
1041
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1042
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1043
                check_inc_file($1);
1044
            $test_inc_before_class = $1;
1045
            $test_inc_before_inline = $3 if ($3);
1046
            print LOGFILE "test_inc_before_class = $param_value\n";
1047
        }
1048
        if ( $param_name =~ /test_inc_inside_class/i ) {
1049
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1050
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1051
                check_inc_file($1);
1052
            $test_inc_inside_class = $1;
1053
            $test_inc_inside_inline = $3 if ($3);
1054
            print LOGFILE "test_inc_inside_class = $param_value\n";
1055
        }
1056
        if ( $param_name =~ /test_inc_after_class/i ) {
1057
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1058
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1059
                check_inc_file($1);
1060
            $test_inc_after_class = $1;
1061
            $test_inc_after_inline = $3 if ($3);
1062
            print LOGFILE "test_inc_after_class = $param_value\n";
1063
        }
1064
 
1065
        if ( $param_name =~ /test_prepend_to_build_phase/i ) {
1066
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1067
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1068
                check_inc_file($1);
1069
            $test_prepend_to_build_phase = $1;
1070
            $test_prepend_to_build_phase_inline = $3 if ($3);
1071
            print LOGFILE "test_prepend_to_build_phase = $param_value\n";
1072
        }
1073
 
1074
        if ( $param_name =~ /test_append_to_build_phase/i ) {
1075
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1076
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1077
                check_inc_file($1);
1078
            $test_append_to_build_phase = $1;
1079
            $test_append_to_build_phase_inline = $3 if ($3);
1080
            print LOGFILE "test_append_to_build_phase = $param_value\n";
1081
        }
1082
 
1083
        if ( $param_name =~ /top_env_generate_methods_inside_class/i ) {
1084
            $top_env_generate_methods_inside_class = uc $param_value;
1085
            print LOGFILE "top_env_generate_methods_inside_class = $param_value\n";
1086
        }
1087
 
1088
        if ( $param_name =~ /top_env_generate_methods_after_class/i ) {
1089
            $top_env_generate_methods_after_class = uc $param_value;
1090
            print LOGFILE "top_env_generate_methods_after_class = $param_value\n";
1091
        }
1092
 
1093
        if ( $param_name =~ /top_env_generate_end_of_elaboration/i ) {
1094
            $top_env_generate_end_of_elaboration = uc $param_value;
1095
            print LOGFILE "top_env_generate_end_of_elaboration = $param_value\n";
1096
        }
1097
 
1098
        if ( $param_name =~ /top_env_generate_run_phase/i ) {
1099
            $top_env_generate_run_phase = uc $param_value;
1100
            print LOGFILE "top_env_generate_run_phase = $param_value\n";
1101
        }
1102
 
1103
        if ( $param_name =~ /top_env_inc_before_class/i ) {
1104
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1105
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1106
                check_inc_file($1);
1107
            $top_env_inc_before_class = $1;
1108
            $top_env_inc_before_inline = $3 if ($3);
1109
            print LOGFILE "top_env_inc_before_class = $param_value\n";
1110
        }
1111
        if ( $param_name =~ /top_env_inc_inside_class/i ) {
1112
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1113
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1114
                check_inc_file($1);
1115
            $top_env_inc_inside_class = $1;
1116
            $top_env_inc_inside_inline = $3 if ($3);
1117
            print LOGFILE "top_env_inc_inside_class = $param_value\n";
1118
        }
1119
        if ( $param_name =~ /top_env_inc_after_class/i ) {
1120
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1121
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1122
                check_inc_file($1);
1123
            $top_env_inc_after_class = $1;
1124
            $top_env_inc_after_inline = $3 if ($3);
1125
            print LOGFILE "top_env_inc_after_class = $param_value\n";
1126
        }
1127
 
1128
        if ( $param_name =~ /top_env_prepend_to_build_phase/i ) {
1129
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1130
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1131
                check_inc_file($1);
1132
            $top_env_prepend_to_build_phase = $1;
1133
            $top_env_prepend_to_build_phase_inline = $3 if ($3);
1134
            print LOGFILE "top_env_prepend_to_build_phase = $param_value\n";
1135
        }
1136
 
1137
        if ( $param_name =~ /top_env_append_to_build_phase/i ) {
1138
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1139
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1140
                check_inc_file($1);
1141
            $top_env_append_to_build_phase = $1;
1142
            $top_env_append_to_build_phase_inline = $3 if ($3);
1143
            print LOGFILE "top_env_append_to_build_phase = $param_value\n";
1144
        }
1145
 
1146
        if ( $param_name =~ /top_env_append_to_connect_phase/i ) {
1147
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1148
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1149
                check_inc_file($1);
1150
            $top_env_append_to_connect_phase = $1;
1151
            $top_env_append_to_connect_phase_inline = $3 if ($3);
1152
            print LOGFILE "top_env_append_to_connect_phase = $param_value\n";
1153
        }
1154
 
1155
        if ( $param_name =~ /top_env_append_to_run_phase/i ) {
1156
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1157
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1158
                check_inc_file($1);
1159
            $top_env_append_to_run_phase = $1;
1160
            $top_env_append_to_run_phase_inline = $3 if ($3);
1161
            print LOGFILE "top_env_append_to_run_phase = $param_value\n";
1162
        }
1163
 
1164
        if ( $param_name =~ /top_env_config_append_to_new/i ) {
1165
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1166
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1167
                check_inc_file($1);
1168
            $top_env_config_append_to_new = $1;
1169
            $top_env_config_append_to_new_inline = $3 if ($3);
1170
            print LOGFILE "top_env_config_append_to_new = $param_value\n";
1171
        }
1172
 
1173
        if ( $param_name =~ /top_env_config_generate_methods_inside_class/i ) {
1174
            $top_env_config_generate_methods_inside_class = uc $param_value;
1175
            print LOGFILE "top_env_config_generate_methods_inside_class = $param_value\n";
1176
        }
1177
 
1178
        if ( $param_name =~ /top_env_config_generate_methods_after_class/i ) {
1179
            $top_env_config_generate_methods_after_class = uc $param_value;
1180
            print LOGFILE "top_env_config_generate_methods_after_class = $param_value\n";
1181
        }
1182
 
1183
        if ( $param_name =~ /top_env_config_inc_before_class/i ) {
1184
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1185
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1186
                check_inc_file($1);
1187
            $top_env_config_inc_before_class = $1;
1188
            $top_env_config_inc_before_inline = $3 if ($3);
1189
            print LOGFILE "top_env_config_inc_before_class = $param_value\n";
1190
        }
1191
        if ( $param_name =~ /top_env_config_inc_inside_class/i ) {
1192
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1193
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1194
                check_inc_file($1);
1195
            $top_env_config_inc_inside_class = $1;
1196
            $top_env_config_inc_inside_inline = $3 if ($3);
1197
            print LOGFILE "top_env_config_inc_inside_class = $param_value\n";
1198
        }
1199
        if ( $param_name =~ /top_env_config_inc_after_class/i ) {
1200
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1201
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1202
                check_inc_file($1);
1203
            $top_env_config_inc_after_class = $1;
1204
            $top_env_config_inc_after_inline = $3 if ($3);
1205
            print LOGFILE "top_env_config_inc_after_class = $param_value\n";
1206
        }
1207
 
1208
        if ( $param_name =~ /top_seq_inc/i ) {
1209
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1210
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1211
                check_inc_file($1);
1212
            $top_seq_inc = $1;
1213
            $top_seq_inc_inline = $3 if ($3);
1214
            print LOGFILE "top_seq_inc = $param_value\n";
1215
        }
1216
 
1217
        if ( $param_name =~ /top_default_seq_count/i ) {
1218
            $top_default_seq_count = $param_value;
1219
            print LOGFILE "top_default_seq_count = $param_value\n";
1220
        }
1221
 
1222
        #check for top-level factory overrides
1223
        if ( $param_name =~ /top_factory_set/i ) {
1224
            $param_value =~ /\s*(\w+)(\s+|\s*,\s*)(\w+)/
1225
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1226
            $top_factory_set{$1} = $3;
1227
            print LOGFILE "top_factory_set = $param_value\n";
1228
        }
1229
 
1230
        #check for config_var
1231
        if ( $param_name =~ /config_var$/i ) {
1232
            print LOGFILE "config_var: $param_value\n";
1233
            push @common_config_var_array, $param_value;
1234
        }
1235
 
1236
        #Syosil scoreboard package source file
1237
        if ( $param_name =~ /syosil_scoreboard_src_path/i ) {
1238
            unless ( defined $syosil_scoreboard_src_path ) {
1239
                check_file($param_value);
1240
                $syosil_scoreboard_src_path = $param_value;
1241
                print LOGFILE "syosil_scoreboard_src_path = $param_value\n";
1242
            }
1243
        }
1244
 
1245
        #check for ref_model inputs
1246
        if ( $param_name =~ /ref_model_input/i ) {
1247
            $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)/
1248
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1249
            unless ( exists $ref_model{$1} ) {
1250
                $ref_model{$1} = 1;
1251
            }
1252
            push @{ $ref_model_inputs{$1} }, $3;
1253
            print LOGFILE "ref_model_input = $1 $3\n";
1254
        }
1255
 
1256
        #check for ref_model outputs
1257
        if ( $param_name =~ /ref_model_output/i ) {
1258
            $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)/
1259
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1260
            unless ( exists $ref_model{$1} ) {
1261
                $ref_model{$1} = 1;
1262
            }
1263
            push @{ $ref_model_outputs{$1} }, $3;
1264
            print LOGFILE "ref_model_output = $1 $3\n";
1265
        }
1266
 
1267
        #check for ref_model compare method
1268
        if ( $param_name =~ /ref_model_compare_method/i ) {
1269
            $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)/
1270
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1271
            unless ( exists $ref_model{$1} ) {
1272
                $ref_model{$1} = 1;
1273
            }
1274
            $ref_model_compare_method{$1} = $3;
1275
            print LOGFILE "ref_model_compare_method = $1 $3\n";
1276
        }
1277
 
1278
        #check for ref_model include files
1279
        if ( $param_name =~ /ref_model_inc_before_class/i ) {
1280
            $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)\s*(,|\s)?\s*(\w*)/
1281
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1282
            my $ref_model_name = $1;
1283
              check_inc_file($3);
1284
            $ref_model_inc_before_class{$ref_model_name} = $3;
1285
            $ref_model_inc_before_inline{$ref_model_name} = $5 if ($5);
1286
            print LOGFILE "ref_model_inc_before_class = $param_value\n";
1287
        }
1288
 
1289
        if ( $param_name =~ /ref_model_inc_inside_class/i ) {
1290
            $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)\s*(,|\s)?\s*(\w*)/
1291
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1292
            my $ref_model_name = $1;
1293
              check_inc_file($3);
1294
            $ref_model_inc_inside_class{$ref_model_name} = $3;
1295
            $ref_model_inc_inside_inline{$ref_model_name} = $5 if ($5);
1296
            print LOGFILE "ref_model_inc_inside_class = $param_value\n";
1297
        }
1298
 
1299
        if ( $param_name =~ /ref_model_inc_after_class/i ) {
1300
            $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)\s*(,|\s)?\s*(\w*)/
1301
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1302
            my $ref_model_name = $1;
1303
              check_inc_file($3);
1304
            $ref_model_inc_after_class{$ref_model_name} = $3;
1305
            $ref_model_inc_after_inline{$ref_model_name} = $5 if ($5);
1306
            print LOGFILE "ref_model_inc_after_class = $param_value\n";
1307
        }
1308
 
1309
        #Acceleration-ready transactors
1310
        if ( $param_name =~ /dual_top/i ) {
1311
            $dual_top = uc $param_value;
1312
            print LOGFILE "dual_top = $param_value\n";
1313
        }
1314
 
1315
        if ( $param_name =~ /split_transactors/i ) {
1316
            $split_transactors = uc $param_value;
1317
            print LOGFILE "split_transactors = $param_value\n";
1318
        }
1319
 
1320
        }
1321
    }
1322
 
1323
    unless ( $tbname ) { $tbname = "top"; }
1324
    printf LOGFILE "prefix for top-level names: $tbname\n";
1325
 
1326
    close TH;
1327
 
1328
}    #end parse_common
1329
 
1330
sub after_parse_common {
1331
 
1332
    if ( defined $top_env_generate_methods_after_class && $top_env_generate_methods_after_class eq "NO" )
1333
    {
1334
        if ( defined $top_env_prepend_to_build_phase ) {
1335
          die "ERROR in ${common_tpl_fname}. top_env_prepend_to_build_phase cannot be used in combination with top_env_generate_methods_after_class = no";
1336
        }
1337
        if ( defined $top_env_append_to_build_phase ) {
1338
          die "ERROR in ${common_tpl_fname}. top_env_append_to_build_phase cannot be used in combination with top_env_generate_methods_after_class = no";
1339
        }
1340
        if ( defined $top_env_append_to_connect_phase ) {
1341
          die "ERROR in ${common_tpl_fname}. top_env_append_to_connect_phase cannot be used in combination with top_env_generate_methods_after_class = no";
1342
        }
1343
        if ( defined $top_env_append_to_run_phase ) {
1344
          die "ERROR in ${common_tpl_fname}. top_env_append_to_run_phase cannot be used in combination with top_env_generate_methods_after_class = no";
1345
        }
1346
    }
1347
 
1348
    if ( defined $test_generate_methods_after_class && $test_generate_methods_after_class eq "NO" )
1349
    {
1350
        if ( defined $test_prepend_to_build_phase )
1351
        {
1352
          die "ERROR in ${common_tpl_fname}. test_prepend_to_build_phase cannot be used in combination with test_generate_methods_after_class = no";
1353
        }
1354
        if ( defined $test_append_to_build_phase )
1355
        {
1356
          die "ERROR in ${common_tpl_fname}. test_append_to_build_phase cannot be used in combination with test_generate_methods_after_class = no";
1357
        }
1358
    }
1359
 
1360
    if ( $split_transactors eq "YES" ) {
1361
        $dual_top = "YES";
1362
    }
1363
}
1364
 
1365
sub deal_with_deprecated_reg_template {
1366
 
1367
    if (defined($flag_regmodel_file)) {
1368
        # With -x regmodel_file, force the script to read the deprecated register model template file reg.tpl if it exists
1369
        $reg_template = "reg.tpl";
1370
    }
1371
 
1372
    parse_reg_template() if ( defined $reg_template and -e $reg_template );
1373
 
1374
    if ( $regmodel ) {
1375
        unless ( defined $top_reg_block_type ) {
1376
            warning_prompt("-r switch given on command line but top-level regmodel block type has not been set");
1377
        }
1378
    }
1379
 
1380
    # The -r switch has been made optional: instantiation of the register model will be forced in the presence of top_reg_block_type (or regmodel_name in reg.tpl)
1381
    if ( defined $top_reg_block_type ) {
1382
        $regmodel = 1
1383
    }
1384
    print LOGFILE "\$regmodel = $regmodel\n";
1385
}
1386
 
1387
sub parse_reg_template {
1388
 
1389
#    print "Register template file reg.tpl still works but is deprecated. Use top_reg_block_type in the common template file and reg_access_block_type in the interface template files instead\n";
1390
    print LOGFILE "\nParsing reg.tpl ...\n\n";
1391
 
1392
    open( TH, $reg_template )
1393
      || die "Exiting due to Error: can't open template: ${reg_template}\n";
1394
 
1395
    for ( ; ; ) {
1396
        my $line;
1397
        undef $!;
1398
        unless ( defined( $line = <TH> ) ) {
1399
            die $! if $!;
1400
            last;    # reached EOF
1401
        }
1402
 
1403
        #next if ($line =~ m/^#/); #comment line starts with "#"
1404
        next if ( $line =~ m/\s*#/ );       #comment line starts with "#"
1405
        next if ( $line =~ m/^\s\s*$/ );    #blank line
1406
 
1407
        $line =~ /^\s*(\w+)\s*=\s*(.+?)\s*$/
1408
          or die "Exiting due to Error: bad entry in line $. of ${reg_template}: $line\n";
1409
        my $param_name  = $1;
1410
        my $param_value = $2;
1411
 
1412
        #check for sub-blocks
1413
        if ( $param_name =~ /rm_sub_block/i or $param_name =~ /regmodel_sub_block/i) {
1414
 
1415
            $param_value =~ /\s*(\w+)(\s+|\s*,\s*)(\w+)/
1416
              or die "Exiting due to Error: bad entry in line $. of ${reg_template}: $line\n";
1417
 
1418
            $reg_access_block_type{$3} = $1;
1419
        }
1420
 
1421
        #check for register model
1422
        if ( $param_name =~ /rm_name/i or $param_name =~ /regmodel_name/i ) {
1423
 
1424
            unless ( defined $top_reg_block_type and $top_reg_block_type ne $param_value) {
1425
                $top_reg_block_type = $param_value;
1426
            }
1427
            else {
1428
                warning_prompt("Top-level regmodel block type set to $param_value in ${reg_template} but already set to $top_reg_block_type");
1429
            }
1430
            print LOGFILE "regmodel_name: $top_reg_block_type\n";
1431
        }
1432
 
1433
        #check for regmodel file
1434
        if ( $param_name =~ /rm_file/i or $param_name =~ /regmodel_file/i) {
1435
                check_file($param_value);
1436
            unless ( $param_value ne $regmodel_file and $regmodel_file ne "regmodel.sv" ) {
1437
                $regmodel_file = $param_value;
1438
            }
1439
            else {
1440
                warning_prompt("regmodel_file set to $param_value in ${reg_template} but already set to $regmodel_file");
1441
            }
1442
            print LOGFILE "regmodel_file: $regmodel_file\n";
1443
        }
1444
    }
1445
    print LOGFILE "\n";
1446
 
1447
    close TH;
1448
}    #end parse_reg_template
1449
 
1450
 
1451
sub handle_minus_x_flag {
1452
 
1453
    if (defined($flag_dut_source_path)) {
1454
        print $dut_path . "\n";
1455
        exit;
1456
    }
1457
    if (defined($flag_inc_path)) {
1458
        print $inc_path . "\n";
1459
        exit;
1460
    }
1461
    if (defined($flag_project)) {
1462
        print $project . "\n";
1463
        exit;
1464
    }
1465
    if (defined($flag_regmodel_file)) {
1466
        if ( $regmodel ) {
1467
            print $regmodel_file . "\n";
1468
        }
1469
        else {
1470
            print "\n";
1471
        }
1472
        exit;
1473
    }
1474
}
1475
 
1476
sub create_directories_and_copy_files {
1477
 
1478
    #create backup of existing project directory
1479
    if (-e $project && $backup ne "NO"){
1480
        print "Copying backup of existing generated files from $project to ${project}.bak\n";
1481
        dircopy( $project, "${project}.bak" ) or die "$!\n";
1482
    }
1483
    mkdir( $project, 0755 );
1484
    $dir = $project . "/sim";
1485
    mkdir( $dir, 0755 );
1486
    $dir = $project . "/tb";
1487
    mkdir( $dir, 0755 );
1488
    $dir = $project . "/tb/" . $tbname;
1489
    mkdir( $dir,         0755 );
1490
    mkdir( $dir . "/sv", 0755 );
1491
    mkdir( $dir . "/sv", 0755 );
1492
    $dir = $project . "/tb/" . $tbname . "_tb";
1493
    mkdir( $dir,         0755 );
1494
    mkdir( $dir . "/sv", 0755 );
1495
    $dir = $project . "/tb/" . $tbname . "_test";
1496
    mkdir( $dir,         0755 );
1497
    mkdir( $dir . "/sv", 0755 );
1498
 
1499
    $dir1 = $dut_path;
1500
    $dut_tb_dir = "dut";
1501
    $dut_tb_path = $project . "/" . $dut_tb_dir;
1502
    $dir2 = $dut_tb_path;
1503
 
1504
    #print LOGFILE "dut_path: $dut_path\n";
1505
    if ( ( -e $dir ) && $dir1 ne $dir2 ) {
1506
        print "Copying dut files to            $dir2\n";
1507
        dircopy( $dir1, $dir2 ) or die "$!\n";
1508
    }
1509
    else {
1510
        print LOGFILE "dut_path does not exist. Nothing to copy from DUT\n";
1511
    }
1512
    if ( -e $inc_path ) {
1513
        $dir1 = $inc_path;
1514
        $dir2 = $project . "/tb/include";
1515
        print "Copying include files to        $dir2\n";
1516
        dircopy( $dir1, $dir2 ) or die "$!\n";
1517
    }
1518
}
1519
 
1520
sub parse_template {
1521
    @agent_var_array         = ();
1522
    @agent_enum_array        = ();
1523
    @agent_meta_array        = ();
1524
    @agent_var_cnstr_array   = ();
1525
    @agent_port_array        = ();
1526
    @agent_clock_array       = ();
1527
    @agent_reset_array       = ();
1528
    $agent_seqr_class        = "";
1529
    @config_var_array        = ();
1530
    $uvm_reg_data            = "";
1531
    $uvm_reg_addr            = "";
1532
    $uvm_reg_kind            = "";
1533
    @additional_agents       = ();
1534
    $agent_has_env           = "NO";
1535
 
1536
    open( TH, $template_name )
1537
      || die "Exiting due to Error: can't open template: " . $template_name . "\n";
1538
 
1539
    for ( ; ; ) {
1540
        my $line;
1541
        undef $!;
1542
        unless ( defined( $line = <TH> ) ) {
1543
            die $! if $!;
1544
            last;    # reached EOF
1545
        }
1546
        next if ( $line =~ m/^\s*#/ );    #comment line starts with "#"
1547
        next if ( $line =~ m/^\s+$/ );    #blank line
1548
 
1549
        $line =~ s/(^.*?)#.*/$1/;         #delete trailing comments
1550
 
1551
        $line =~ /^\s*(\w+)\s*=\s*(.*?)\s*$/
1552
          or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1553
        my $param_name  = $1;
1554
        my $param_value = $2;
1555
 
1556
        #check for agent_name
1557
        if ( $param_name =~ /agent_name/i ) {
1558
            print LOGFILE "agent_name: $line";
1559
            $agent_name = $param_value;
1560
            if ( $agent_name eq "") {
1561
                warning_prompt("agent_name is blank in ${template_name}");
1562
            }
1563
            push( @agent_list, $agent_name );
1564
 
1565
            # Set values and defaults that depend on agent name
1566
            $number_of_instances{$agent_name}   = 1;
1567
            $tpl_fname{$agent_name}             = $template_name;
1568
            $agent_if                           = "${agent_name}_if";
1569
            $if_instance_names{$agent_if}       = "${agent_if}_0";
1570
            $if_instance_names{"${agent_if}_0"} = "${agent_if}_0";
1571
            if ( $split_transactors eq "YES" ) {
1572
                push( @all_agent_ifs, "${agent_name}_bfm" );
1573
            }
1574
            else {
1575
                push( @all_agent_ifs, $agent_if );
1576
            }
1577
        }
1578
 
1579
        #number of instances of the agent and its interface
1580
        if ( $param_name =~ /number_of_instances/i ) {
1581
            $number_of_instances{$agent_name} = $param_value;
1582
            print LOGFILE "number_of_instances = $param_value\n";
1583
            if ($param_value > 1) {
1584
                for ( my $i = 1 ; $i < $param_value ; $i++ ) {
1585
                    $if_instance_names{"${agent_if}_${i}"} = "${agent_if}_${i}";
1586
                }
1587
            }
1588
        }
1589
 
1590
        #check if agent has its own env (default = NO)
1591
        if ( $param_name =~ /agent_has_env/i ) {
1592
            $agent_has_env = uc $param_value;
1593
        }
1594
 
1595
        #check if other agents to be added to same env
1596
        if ( $param_name =~ /additional_agent/i ) {
1597
            push @additional_agents, $param_value;
1598
            unless ( exists $agent_parent{$param_value} ) {
1599
                $agent_parent{$param_value} = $agent_name;
1600
            }
1601
            else {
1602
                warning_prompt("An agent should not appear as an additional_agent more than once: $param_value is an additional_agent in $agent_name and $agent_parent{$param_value}");
1603
            }
1604
        }
1605
 
1606
        #check for uvm_seqr_class
1607
        if ( $param_name =~ /uvm_seqr_class/i ) {
1608
            $agent_seqr_class = $param_value;
1609
        }
1610
 
1611
        #check for active/passive agent
1612
        if ( $param_name =~ /agent_is_active/i ) {
1613
            my $value = uc $param_value;
1614
            if ( $value ne "UVM_ACTIVE" && $value ne "UVM_PASSIVE" ) {
1615
                warning_prompt("agent_is_active must be either UVM_ACTIVE or UVM_PASSIVE in template file: ${template_name}");
1616
            }
1617
            $agent_is_active{$agent_name} = $value;
1618
        }
1619
 
1620
        #check for agent checks_enable (default = YES)
1621
        if ( $param_name =~ /agent_checks_enable/i ) {
1622
            $agent_checks_enable{$agent_name} = uc $param_value;
1623
        }
1624
 
1625
        #check for agent coverage_enable (default = YES)
1626
        if ( $param_name =~ /agent_coverage_enable/i ) {
1627
            $agent_coverage_enable{$agent_name} = uc $param_value;
1628
        }
1629
 
1630
        #check for trans_item
1631
        if ( $param_name =~ /trans_item/i ) {
1632
            $agent_item = $param_value;
1633
            print LOGFILE "trans_item= $agent_item\n";
1634
            $agent_item_types{$agent_name} = $agent_item;
1635
        }
1636
 
1637
        #check for trans_var
1638
        if ( $param_name =~ /trans_var$/i ) {
1639
            print LOGFILE "trans_var: $param_value\n";
1640
            push @agent_var_array, $param_value
1641
        }
1642
 
1643
        #check for trans_enum and trans_meta
1644
        if ( $param_name =~ /trans_enum_var$/i ) {
1645
            print LOGFILE "trans_enum_var: $param_value\n";
1646
            push @agent_var_array, $param_value;
1647
            push @agent_enum_array, $param_value;
1648
        }
1649
 
1650
        if ( $param_name =~ /trans_meta$/i ) {
1651
            print LOGFILE "trans_meta: $param_value\n";
1652
            push @agent_meta_array, $param_value;
1653
        }
1654
 
1655
        if ( $param_name =~ /trans_enum_meta$/i) {
1656
            print LOGFILE "trans_enum_meta: $param_value\n";
1657
            push @agent_meta_array, $param_value;
1658
            push @agent_enum_array, $param_value;
1659
        }
1660
 
1661
        #check for trans_var_constraint
1662
        if ( $param_name =~ /trans_var_constraint/i ) {
1663
            print LOGFILE "trans_var_constraint: $param_value\n";
1664
            push @agent_var_cnstr_array, $param_value;
1665
       }
1666
 
1667
        #check for config_var
1668
        if ( $param_name =~ /config_var$/i ) {
1669
            print LOGFILE "config_var: $param_value\n";
1670
            push @config_var_array, $param_value;
1671
        }
1672
 
1673
        #check for agent sequence include file
1674
        if ( $param_name =~ /agent_seq_inc/i ) {
1675
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1676
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1677
              check_inc_file($1);
1678
            $agent_seq_inc{$agent_name} = $1;
1679
            $agent_seq_inc_inline{$agent_name} = $3 if ($3);
1680
            print LOGFILE "agent_seq_inc = $param_value\n";
1681
        }
1682
 
1683
        #check for agent include file
1684
        if ( $param_name =~ /agent_generate_methods_inside_class/i ) {
1685
            $agent_generate_methods_inside_class{$agent_name} = uc $param_value;
1686
            print LOGFILE "agent_generate_methods_inside_class = $param_value\n";
1687
        }
1688
 
1689
        if ( $param_name =~ /agent_generate_methods_after_class/i ) {
1690
            $agent_generate_methods_after_class{$agent_name} = uc $param_value;
1691
            print LOGFILE "agent_generate_methods_after_class = $param_value\n";
1692
        }
1693
 
1694
        if ( $param_name =~ /agent_inc_before_class/i ) {
1695
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1696
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1697
              check_inc_file($1);
1698
            $agent_inc_before_class{$agent_name} = $1;
1699
            $agent_inc_before_inline{$agent_name} = $3 if ($3);
1700
            print LOGFILE "agent_inc_before_class = $param_value\n";
1701
        }
1702
 
1703
        if ( $param_name =~ /agent_inc_inside_class/i ) {
1704
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1705
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1706
              check_inc_file($1);
1707
            $agent_inc_inside_class{$agent_name} = $1;
1708
            $agent_inc_inside_inline{$agent_name} = $3 if ($3);
1709
            print LOGFILE "agent_inc_inside_class = $param_value\n";
1710
        }
1711
 
1712
        if ( $param_name =~ /agent_inc_after_class/i ) {
1713
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1714
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1715
              check_inc_file($1);
1716
            $agent_inc_after_class{$agent_name} = $1;
1717
            $agent_inc_after_inline{$agent_name} = $3 if ($3);
1718
            print LOGFILE "agent_inc_after_class = $param_value\n";
1719
        }
1720
 
1721
        if ( $param_name =~ /agent_inc_inside_bfm/i ) {
1722
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1723
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1724
              check_inc_file($1);
1725
            $agent_inc_inside_bfm{$agent_name} = $1;
1726
            $agent_inc_inside_bfm_inline{$agent_name} = $3 if ($3);
1727
            print LOGFILE "agent_inc_inside_bfm = $param_value\n";
1728
        }
1729
 
1730
        if ( $param_name =~ /agent_prepend_to_build_phase/i ) {
1731
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1732
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1733
              check_inc_file($1);
1734
            $agent_prepend_to_build_phase{$agent_name} = $1;
1735
            $agent_prepend_to_build_phase_inline{$agent_name} = $3 if ($3);
1736
            print LOGFILE "agent_prepend_to_build_phase = $param_value\n";
1737
        }
1738
 
1739
        if ( $param_name =~ /agent_append_to_build_phase/i ) {
1740
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1741
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1742
              check_inc_file($1);
1743
            $agent_append_to_build_phase{$agent_name} = $1;
1744
            $agent_append_to_build_phase_inline{$agent_name} = $3 if ($3);
1745
            print LOGFILE "agent_append_to_build_phase = $param_value\n";
1746
        }
1747
 
1748
        if ( $param_name =~ /agent_append_to_connect_phase/i ) {
1749
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1750
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1751
              check_inc_file($1);
1752
            $agent_append_to_connect_phase{$agent_name} = $1;
1753
            $agent_append_to_connect_phase_inline{$agent_name} = $3 if ($3);
1754
            print LOGFILE "agent_append_to_connect_phase = $param_value\n";
1755
        }
1756
 
1757
        if ( $param_name =~ /agent_copy_config_vars/i ) {
1758
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1759
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1760
              check_inc_file($1);
1761
            $agent_copy_config_vars{$agent_name} = $1;
1762
            $agent_copy_config_vars_inline{$agent_name} = $3 if ($3);
1763
            print LOGFILE "agent_copy_config_vars = $param_value\n";
1764
        }
1765
 
1766
        #check for agent environment sequence include file
1767
        if ( $param_name =~ /agent_env_seq_inc/i ) {
1768
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1769
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1770
              check_inc_file($1);
1771
            $agent_env_seq_inc{$agent_name} = $1;
1772
            $agent_env_seq_inc_inline{$agent_name} = $3 if ($3);
1773
            print LOGFILE "agent_env_seq_inc = $param_value\n";
1774
        }
1775
 
1776
        #check for agent env include file
1777
        if ( $param_name =~ /agent_env_generate_methods_inside_class/i ) {
1778
            $agent_env_generate_methods_inside_class{$agent_name} = uc $param_value;
1779
            print LOGFILE "agent_env_generate_methods_inside_class = $param_value\n";
1780
        }
1781
 
1782
        if ( $param_name =~ /agent_env_generate_methods_after_class/i ) {
1783
            $agent_env_generate_methods_after_class{$agent_name} = uc $param_value;
1784
            print LOGFILE "agent_env_generate_methods_after_class = $param_value\n";
1785
        }
1786
 
1787
        if ( $param_name =~ /agent_env_inc_before_class/i ) {
1788
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1789
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1790
              check_inc_file($1);
1791
            $agent_env_inc_before_class{$agent_name} = $1;
1792
            $agent_env_inc_before_inline{$agent_name} = $3 if ($3);
1793
            print LOGFILE "agent_env_inc_before_class = $param_value\n";
1794
        }
1795
 
1796
        if ( $param_name =~ /agent_env_inc_inside_class/i ) {
1797
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1798
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1799
              check_inc_file($1);
1800
            $agent_env_inc_inside_class{$agent_name} = $1;
1801
            $agent_env_inc_inside_inline{$agent_name} = $3 if ($3);
1802
            print LOGFILE "agent_env_inc_inside_class = $param_value\n";
1803
        }
1804
 
1805
        if ( $param_name =~ /agent_env_inc_after_class/i ) {
1806
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1807
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1808
              check_inc_file($1);
1809
            $agent_env_inc_after_class{$agent_name} = $1;
1810
            $agent_env_inc_after_inline{$agent_name} = $3 if ($3);
1811
            print LOGFILE "agent_env_inc_after_class = $param_value\n";
1812
        }
1813
 
1814
        if ( $param_name =~ /agent_env_prepend_to_build_phase/i ) {
1815
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1816
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1817
              check_inc_file($1);
1818
            $agent_env_prepend_to_build_phase{$agent_name} = $1;
1819
            $agent_env_prepend_to_build_phase_inline{$agent_name} = $3 if ($3);
1820
            print LOGFILE "agent_env_prepend_to_build_phase = $param_value\n";
1821
        }
1822
 
1823
        if ( $param_name =~ /agent_env_append_to_build_phase/i ) {
1824
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1825
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1826
              check_inc_file($1);
1827
            $agent_env_append_to_build_phase{$agent_name} = $1;
1828
            $agent_env_append_to_build_phase_inline{$agent_name} = $3 if ($3);
1829
            print LOGFILE "agent_env_append_to_build_phase = $param_value\n";
1830
        }
1831
 
1832
        if ( $param_name =~ /agent_env_append_to_connect_phase/i ) {
1833
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1834
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1835
              check_inc_file($1);
1836
            $agent_env_append_to_connect_phase{$agent_name} = $1;
1837
            $agent_env_append_to_connect_phase_inline{$agent_name} = $3 if ($3);
1838
            print LOGFILE "agent_env_append_to_connect_phase = $param_value\n";
1839
        }
1840
 
1841
        if ( $param_name =~ /adapter_generate_methods_inside_class/i ) {
1842
            $agent_adapter_generate_methods_inside_class{$agent_name} = uc $param_value;
1843
            print LOGFILE "adapter_generate_methods_inside_class = $param_value\n";
1844
        }
1845
 
1846
        if ( $param_name =~ /adapter_generate_methods_after_class/i ) {
1847
            $agent_adapter_generate_methods_after_class{$agent_name} = uc $param_value;
1848
            print LOGFILE "adapter_generate_methods_after_class = $param_value\n";
1849
        }
1850
 
1851
        if ( $param_name =~ /adapter_inc_before_class/i ) {
1852
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1853
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1854
              check_inc_file($1);
1855
            $agent_adapter_inc_before_class{$agent_name} = $1;
1856
            $agent_adapter_inc_before_inline{$agent_name} = $3 if ($3);
1857
            print LOGFILE "agent_adapter_inc_before_class = $param_value\n";
1858
        }
1859
 
1860
        if ( $param_name =~ /adapter_inc_inside_class/i ) {
1861
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1862
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1863
              check_inc_file($1);
1864
            $agent_adapter_inc_inside_class{$agent_name} = $1;
1865
            $agent_adapter_inc_inside_inline{$agent_name} = $3 if ($3);
1866
            print LOGFILE "agent_adapter_inc_inside_class = $param_value\n";
1867
        }
1868
 
1869
        if ( $param_name =~ /adapter_inc_after_class/i ) {
1870
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1871
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1872
              check_inc_file($1);
1873
            $agent_adapter_inc_after_class{$agent_name} = $1;
1874
            $agent_adapter_inc_after_inline{$agent_name} = $3 if ($3);
1875
            print LOGFILE "agent_adapter_inc_after_class = $param_value\n";
1876
        }
1877
 
1878
        if ( $param_name =~ /byo_interface/i ) {
1879
            $byo_interface{$agent_name} = $param_value;
1880
            print LOGFILE "byo_interface = $param_value\n";
1881
        }
1882
 
1883
        if ( $param_name =~ /generate_interface_instance/i ) {
1884
            $generate_interface_instance{$agent_name} = uc $param_value;
1885
            print LOGFILE "generate_interface_instance = $param_value\n";
1886
        }
1887
 
1888
        if ( $param_name =~ /if_inc_inside_interface/i ) {
1889
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1890
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1891
              check_inc_file($1);
1892
            $if_inc_inside_interface{$agent_name} = $1;
1893
            $if_inc_inside_inline{$agent_name} = $3 if ($3);
1894
            print LOGFILE "if_inc_inside_interface = $param_value\n";
1895
        }
1896
 
1897
        if ( $param_name =~ /trans_generate_methods_inside_class/i ) {
1898
            $agent_trans_generate_methods_inside_class{$agent_name} = uc $param_value;
1899
            print LOGFILE "trans_generate_methods_inside_class = $param_value\n";
1900
        }
1901
 
1902
        if ( $param_name =~ /trans_generate_methods_after_class/i ) {
1903
            $agent_trans_generate_methods_after_class{$agent_name} = uc $param_value;
1904
            print LOGFILE "trans_generate_methods_after_class = $param_value\n";
1905
        }
1906
 
1907
        if ( $param_name =~ /trans_inc_before_class/i ) {
1908
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1909
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1910
              check_inc_file($1);
1911
            $agent_trans_inc_before_class{$agent_name} = $1;
1912
            $agent_trans_inc_before_inline{$agent_name} = $3 if ($3);
1913
            print LOGFILE "trans_inc_before_class = $param_value\n";
1914
        }
1915
 
1916
        if ( $param_name =~ /trans_inc_inside_class/i ) {
1917
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1918
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1919
              check_inc_file($1);
1920
            $agent_trans_inc_inside_class{$agent_name} = $1;
1921
            $agent_trans_inc_inside_inline{$agent_name} = $3 if ($3);
1922
            print LOGFILE "trans_inc_inside_class = $param_value\n";
1923
        }
1924
 
1925
        if ( $param_name =~ /trans_inc_after_class/i ) {
1926
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1927
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1928
              check_inc_file($1);
1929
            $agent_trans_inc_after_class{$agent_name} = $1;
1930
            $agent_trans_inc_after_inline{$agent_name} = $3 if ($3);
1931
            print LOGFILE "trans_inc_after_class = $param_value\n";
1932
        }
1933
 
1934
        if ( $param_name =~ /agent_config_generate_methods_inside_class/i ) {
1935
            $agent_config_generate_methods_inside_class{$agent_name} = uc $param_value;
1936
            print LOGFILE "agent_config_generate_methods_inside_class = $param_value\n";
1937
        }
1938
 
1939
        if ( $param_name =~ /agent_config_generate_methods_after_class/i ) {
1940
            $agent_config_generate_methods_after_class{$agent_name} = uc $param_value;
1941
            print LOGFILE "agent_config_generate_methods_after_class = $param_value\n";
1942
        }
1943
 
1944
        if ( $param_name =~ /agent_config_inc_before_class/i ) {
1945
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1946
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1947
              check_inc_file($1);
1948
            $agent_config_inc_before_class{$agent_name} = $1;
1949
            $agent_config_inc_before_inline{$agent_name} = $3 if ($3);
1950
            print LOGFILE "agent_config_inc_before_class = $param_value\n";
1951
        }
1952
 
1953
        if ( $param_name =~ /agent_config_inc_inside_class/i ) {
1954
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1955
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1956
              check_inc_file($1);
1957
            $agent_config_inc_inside_class{$agent_name} = $1;
1958
            $agent_config_inc_inside_inline{$agent_name} = $3 if ($3);
1959
            print LOGFILE "agent_config_inc_inside_class = $param_value\n";
1960
        }
1961
 
1962
        if ( $param_name =~ /agent_config_inc_after_class/i ) {
1963
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1964
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1965
              check_inc_file($1);
1966
            $agent_config_inc_after_class{$agent_name} = $1;
1967
            $agent_config_inc_after_inline{$agent_name} = $3 if ($3);
1968
            print LOGFILE "agent_config_inc_after_class = $param_value\n";
1969
        }
1970
 
1971
        #check for agent coverpoint include file
1972
        if ( $param_name =~ /agent_cover_generate_methods_inside_class/i ) {
1973
            $agent_cover_generate_methods_inside_class{$agent_name} = uc $param_value;
1974
            print LOGFILE "agent_cover_generate_methods_inside_class = $param_value\n";
1975
        }
1976
 
1977
        if ( $param_name =~ /agent_cover_generate_methods_after_class/i ) {
1978
            $agent_cover_generate_methods_after_class{$agent_name} = uc $param_value;
1979
            print LOGFILE "agent_cover_generate_methods_after_class = $param_value\n";
1980
        }
1981
 
1982
        if ( $param_name =~ /agent_cover_inc\b/i ) {
1983
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1984
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1985
              check_inc_file($1);
1986
            $agent_cover_inc{$agent_name} = $1;
1987
            $agent_cover_inc_inline{$agent_name} = $3 if ($3);
1988
            print LOGFILE "agent_cover_inc = $param_value\n";
1989
        }
1990
 
1991
        if ( $param_name =~ /agent_cover_inc_before_class/i ) {
1992
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
1993
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
1994
              check_inc_file($1);
1995
            $agent_cover_inc_before_class{$agent_name} = $1;
1996
            $agent_cover_inc_before_inline{$agent_name} = $3 if ($3);
1997
            print LOGFILE "agent_cover_inc_before_class = $param_value\n";
1998
        }
1999
 
2000
        if ( $param_name =~ /agent_cover_inc_inside_class/i ) {
2001
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2002
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2003
              check_inc_file($1);
2004
            $agent_cover_inc_inside_class{$agent_name} = $1;
2005
            $agent_cover_inc_inside_inline{$agent_name} = $3 if ($3);
2006
            print LOGFILE "agent_cover_inc_inside_class = $param_value\n";
2007
        }
2008
 
2009
        if ( $param_name =~ /agent_cover_inc_after_class/i ) {
2010
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2011
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2012
              check_inc_file($1);
2013
            $agent_cover_inc_after_class{$agent_name} = $1;
2014
            $agent_cover_inc_after_inline{$agent_name} = $3 if ($3);
2015
            print LOGFILE "agent_cover_inc_after_class = $param_value\n";
2016
        }
2017
 
2018
        #check for driver include file
2019
        if ( $param_name =~ /driver_inc\b/i ) {
2020
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2021
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2022
              check_inc_file($1);
2023
            $agent_driv_inc{$agent_name} = $1;
2024
            $agent_driv_inc_inline{$agent_name} = $3 if ($3);
2025
            print LOGFILE "driver_inc = $param_value\n";
2026
        }
2027
 
2028
        if ( $param_name =~ /driver_inc_before_class/i ) {
2029
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2030
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2031
              check_inc_file($1);
2032
            $agent_driv_inc_before_class{$agent_name} = $1;
2033
            $agent_driv_inc_before_inline{$agent_name} = $3 if ($3);
2034
            print LOGFILE "driver_inc_before_class = $param_value\n";
2035
        }
2036
 
2037
        if ( $param_name =~ /driver_inc_inside_class/i ) {
2038
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2039
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2040
              check_inc_file($1);
2041
            $agent_driv_inc_inside_class{$agent_name} = $1;
2042
            $agent_driv_inc_inside_inline{$agent_name} = $3 if ($3);
2043
            print LOGFILE "driver_inc_inside_class = $param_value\n";
2044
        }
2045
 
2046
        if ( $param_name =~ /driver_inc_after_class/i ) {
2047
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2048
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2049
              check_inc_file($1);
2050
            $agent_driv_inc_after_class{$agent_name} = $1;
2051
            $agent_driv_inc_after_inline{$agent_name} = $3 if ($3);
2052
            print LOGFILE "driver_inc_after_class = $param_value\n";
2053
        }
2054
 
2055
        #check for monitor include file
2056
        if ( $param_name =~ /monitor_inc\b/i ) {
2057
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2058
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2059
              check_inc_file($1);
2060
            $agent_mon_inc{$agent_name} = $1;
2061
            $agent_mon_inc_inline{$agent_name} = $3 if ($3);
2062
            print LOGFILE "monitor_inc = $param_value\n";
2063
        }
2064
 
2065
        if ( $param_name =~ /monitor_inc_before_class/i ) {
2066
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2067
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2068
              check_inc_file($1);
2069
            $agent_mon_inc_before_class{$agent_name} = $1;
2070
            $agent_mon_inc_before_inline{$agent_name} = $3 if ($3);
2071
            print LOGFILE "monitor_inc_before_class = $param_value\n";
2072
        }
2073
 
2074
        if ( $param_name =~ /monitor_inc_inside_class/i ) {
2075
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2076
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2077
              check_inc_file($1);
2078
            $agent_mon_inc_inside_class{$agent_name} = $1;
2079
            $agent_mon_inc_inside_inline{$agent_name} = $3 if ($3);
2080
            print LOGFILE "monitor_inc_inside_class = $param_value\n";
2081
        }
2082
 
2083
        if ( $param_name =~ /monitor_inc_after_class/i ) {
2084
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2085
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2086
              check_inc_file($1);
2087
            $agent_mon_inc_after_class{$agent_name} = $1;
2088
            $agent_mon_inc_after_inline{$agent_name} = $3 if ($3);
2089
            print LOGFILE "monitor_inc_after_class = $param_value\n";
2090
        }
2091
 
2092
        #check for sequencer include file
2093
        if ( $param_name =~ /sequencer_inc_before_class/i ) {
2094
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2095
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2096
              check_inc_file($1);
2097
            $agent_seqr_inc_before_class{$agent_name} = $1;
2098
            $agent_seqr_inc_before_inline{$agent_name} = $3 if ($3);
2099
            print LOGFILE "sequencer_inc_before_class = $param_value\n";
2100
        }
2101
 
2102
        if ( $param_name =~ /sequencer_inc_inside_class/i ) {
2103
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2104
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2105
              check_inc_file($1);
2106
            $agent_seqr_inc_inside_class{$agent_name} = $1;
2107
            $agent_seqr_inc_inside_inline{$agent_name} = $3 if ($3);
2108
            print LOGFILE "sequencer_inc_inside_class = $param_value\n";
2109
        }
2110
 
2111
        if ( $param_name =~ /sequencer_inc_after_class/i ) {
2112
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2113
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2114
              check_inc_file($1);
2115
            $agent_seqr_inc_after_class{$agent_name} = $1;
2116
            $agent_seqr_inc_after_inline{$agent_name} = $3 if ($3);
2117
            print LOGFILE "sequencer_inc_after_class = $param_value\n";
2118
        }
2119
 
2120
        #check for if_port
2121
        if ( $param_name =~ /if_port/i ) {
2122
            my $agent_port = $param_value;
2123
            push @agent_port_array, $agent_port;
2124
            print LOGFILE "if_port = $param_value\n";
2125
        }
2126
 
2127
        #check for if_clock
2128
        if ( $param_name =~ /if_clock/i ) {
2129
            my $agent_clock = $param_value;
2130
            push @agent_clock_array, $agent_clock;
2131
            $env_clock_list =
2132
              $env_clock_list
2133
              ? "$env_clock_list $agent_name $agent_clock"
2134
              : "$agent_name $agent_clock";
2135
            print LOGFILE "env_clock_list: $env_clock_list\n";
2136
        }
2137
        @clist = split( /\s+/, $env_clock_list );
2138
        foreach $i ( 0 .. @clist-1 ) {
2139
            if ( $clist[$i] ne "" ) {
2140
                print LOGFILE "clist[$i]: $clist[$i]\n";
2141
            }
2142
        }
2143
 
2144
        #check for if_reset
2145
        if ( $param_name =~ /if_reset/i ) {
2146
            $agent_reset = $param_value;
2147
            print LOGFILE "IF_RESET: $agent_reset\n";
2148
            push @agent_reset_array, $agent_reset;
2149
            $env_reset_list =
2150
              $env_reset_list
2151
              ? "$env_reset_list $agent_name $agent_reset"
2152
              : "$agent_name $agent_reset";
2153
            print LOGFILE "env_reset_list: $env_reset_list\n";
2154
        }
2155
        @rlist = split( /\s+/, $env_reset_list );
2156
        foreach $i ( 0 .. @rlist-1 ) {
2157
            if ( $rlist[$i] ne "" ) {
2158
                print LOGFILE "rlist[$i]: $rlist[$i]\n";
2159
            }
2160
        }
2161
 
2162
        #check for reg_access (gives addr map in uvm_reg)
2163
        if ( $param_name =~ /reg_access_name/i ) {
2164
            print "reg_access_name in ${template_name} still works but is deprecated. Use reg_access_mode instead. You can also set reg_access_block_type, reg_access_block_instance, and reg_access_map\n";
2165
            $param_value =~ /\s*(\w+)(\s+|\s*,\s*)(\w+)/
2166
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2167
            unless ( exists $reg_access_mode{$agent_name} and $reg_access_mode{$agent_name} ne $3 ) {
2168
                $reg_access_mode{$agent_name} = $3;
2169
            }
2170
            else {
2171
                warning_prompt("reg_access_name sets mode to $3 in ${template_name} but it is already set to a different value ($reg_access_mode{$agent_name})");
2172
            }
2173
            print LOGFILE "reg_access_name: $param_value\n";
2174
        }
2175
 
2176
        if ( $param_name =~ /reg_access_block_type/i ) {
2177
            $param_value =~ /\s*(\w+)/
2178
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2179
            unless ( exists $reg_access_block_type{$agent_name} and $reg_access_block_type{$agent_name} ne $1 ) {
2180
                $reg_access_block_type{$agent_name} = $1;
2181
            }
2182
            else {
2183
                warning_prompt("reg_access_block_type set to $1 in ${template_name} but it is already set to a different value ($reg_access_block_type{$agent_name})");
2184
            }
2185
            print LOGFILE "reg_access_block_type: $1\n";
2186
        }
2187
 
2188
        if ( $param_name =~ /reg_access_block_instance/i ) {
2189
            $param_value =~ /\s*([\w\.]*)/
2190
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2191
            my $instance = $1;
2192
            if ( $instance ne "" ) {
2193
                if ( substr($instance, 0, 1) ne "." ) {
2194
                   $instance = ".$instance";
2195
                }
2196
            }
2197
            unless ( exists $reg_access_instance{$agent_name} and $reg_access_instance{$agent_name} ne $instance ) {
2198
                $reg_access_instance{$agent_name} = $instance;
2199
            }
2200
            else {
2201
                warning_prompt("reg_access_block_instance set to $1 in ${template_name} but it is already set to a different value ($reg_access_instance{$agent_name})");
2202
            }
2203
            print LOGFILE "reg_access_block_instance: $instance\n";
2204
        }
2205
 
2206
        if ( $param_name =~ /reg_access_map/i ) {
2207
            $param_value =~ /\s*(\w+)/
2208
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2209
            $reg_access_map{$agent_name} = $1;
2210
            print LOGFILE "reg_access_map: $1\n";
2211
        }
2212
 
2213
        if ( $param_name =~ /reg_access_mode/i ) {
2214
            $param_value =~ /\s*(\w+)/
2215
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2216
            unless ( exists $reg_access_mode{$agent_name} and $reg_access_mode{$agent_name} ne $1 ) {
2217
                $reg_access_mode{$agent_name} = $1;
2218
            }
2219
            else {
2220
                warning_prompt("reg_access_mode set to $1 in ${template_name} but it is already set to a different value ($reg_access_mode{$agent_name})");
2221
            }
2222
            print LOGFILE "reg_access_mode: $1\n";
2223
        }
2224
 
2225
        #check for uvm_reg to bus mappings
2226
        if ( $param_name =~ /uvm_reg_data/i ) {
2227
            $uvm_reg_data = $param_value;
2228
        }
2229
        if ( $param_name =~ /uvm_reg_addr/i ) {
2230
            $uvm_reg_addr = $param_value;
2231
        }
2232
        if ( $param_name =~ /uvm_reg_kind/i ) {
2233
            $uvm_reg_kind = $param_value;
2234
        }
2235
 
2236
        #check for register sequence include file (an alias for agent_env_seq_inc)
2237
        if ( $param_name =~ /reg_seq_inc/i ) {
2238
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2239
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2240
              check_inc_file($1);
2241
            $agent_env_seq_inc{$agent_name} = $1;
2242
            $agent_env_seq_inc_inline{$agent_name} = $3 if ($3);
2243
            print LOGFILE "reg_seq_inc = $param_value\n";
2244
        }
2245
 
2246
        #check for register coverpoint include file
2247
        if ( $param_name =~ /reg_cover_generate_methods_inside_class/i ) {
2248
            $reg_cover_generate_methods_inside_class{$agent_name} = uc $param_value;
2249
            print LOGFILE "reg_cover_generate_methods_inside_class = $param_value\n";
2250
        }
2251
 
2252
        if ( $param_name =~ /reg_cover_generate_methods_after_class/i ) {
2253
            $reg_cover_generate_methods_after_class{$agent_name} = uc $param_value;
2254
            print LOGFILE "reg_cover_generate_methods_after_class = $param_value\n";
2255
        }
2256
 
2257
        if ( $param_name =~ /reg_cover_inc\b/i ) {
2258
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2259
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2260
              check_inc_file($1);
2261
            $reg_cover_inc{$agent_name} = $1;
2262
            $reg_cover_inc_inline{$agent_name} = $3 if ($3);
2263
            print LOGFILE "reg_cover_inc = $param_value\n";
2264
        }
2265
 
2266
        if ( $param_name =~ /reg_cover_inc_before_class/i ) {
2267
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2268
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2269
              check_inc_file($1);
2270
            $reg_cover_inc_before_class{$agent_name} = $1;
2271
            $reg_cover_inc_before_inline{$agent_name} = $3 if ($3);
2272
            print LOGFILE "reg_cover_inc_before_class = $param_value\n";
2273
        }
2274
 
2275
        if ( $param_name =~ /reg_cover_inc_inside_class/i ) {
2276
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2277
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2278
              check_inc_file($1);
2279
            $reg_cover_inc_inside_class{$agent_name} = $1;
2280
            $reg_cover_inc_inside_inline{$agent_name} = $3 if ($3);
2281
            print LOGFILE "reg_cover_inc_inside_class = $param_value\n";
2282
        }
2283
 
2284
        if ( $param_name =~ /reg_cover_inc_after_class/i ) {
2285
            $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/
2286
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2287
              check_inc_file($1);
2288
            $reg_cover_inc_after_class{$agent_name} = $1;
2289
            $reg_cover_inc_after_inline{$agent_name} = $3 if ($3);
2290
            print LOGFILE "reg_cover_inc_after_class = $param_value\n";
2291
        }
2292
 
2293
        #check for factory overrides
2294
        if ( $param_name =~ /agent_factory_set/i ) {
2295
            $param_value =~ /\s*(\w+)(\s+|\s*,\s*)(\w+)/
2296
              or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n";
2297
            $agent_factory_set{$1} = $3;
2298
        }
2299
 
2300
    } # End of file parsing loop
2301
 
2302
    close TH;
2303
}    #end parse_template
2304
 
2305
sub after_parse_template {
2306
 
2307
    if ( exists $reg_access_mode{$agent_name} ) {
2308
 
2309
        $bus2reg_map{$agent_name} = {
2310
            'data' => $uvm_reg_data,
2311
            'addr' => $uvm_reg_addr,
2312
            'kind' => $uvm_reg_kind
2313
        };
2314
 
2315
        if ( @additional_agents ) {
2316
            warning_prompt("additional_agent and reg_access_name/mode/type/instance are mutually exclusive and should not be used in the same template file: ${template_name}");
2317
        }
2318
 
2319
        unless ( exists $reg_access_instance{$agent_name} ) {
2320
            $reg_access_instance{$agent_name} = ".${agent_name}";
2321
        }
2322
        unless ( exists $reg_access_map{$agent_name} ) {
2323
            $reg_access_map{$agent_name} = "${agent_name}_map";
2324
        }
2325
        unless ( exists $reg_access_block_type{$agent_name} ) {
2326
            warning_prompt("reg_access_name or reg_access_mode are set without setting reg_access_block_type or regmodel_sub_block in template file: ${template_name}");
2327
        }
2328
 
2329
        if ( $number_of_instances{$agent_name} > 1 ) {
2330
            warning_prompt("Agent $agent_name uses reg_access_* but has number_of_instances = $number_of_instances{$agent_name} in ${template_name}." .
2331
                           " reg_access_instance and reg_access_map will get the suffix _N. This will change in future versions of the generator.");
2332
        }
2333
 
2334
        if ( $agent_has_env eq "NO" ) {
2335
              print "Forcing agent_has_env = yes for agent ${agent_name} because the agent uses register access\n";
2336
        }
2337
        $agent_has_env = "YES";
2338
 
2339
        if ( exists $agent_is_active{$agent_name} and $agent_is_active{$agent_name} eq "UVM_PASSIVE" ) {
2340
            warning_prompt("Agent $agent_name uses reg_access_* but has agent_is_active = UVM_PASSIVE in template file: ${template_name}");
2341
        }
2342
    }
2343
    else
2344
    {
2345
        if ( exists $reg_access_block_type{$agent_name} ) {
2346
            warning_prompt("reg_access_block_type or regmodel_sub_block are set without setting reg_access_name or reg_access_mode in template file: ${template_name}");
2347
        }
2348
        if ( exists $reg_access_map{$agent_name} ) {
2349
            warning_prompt("reg_access_map is set without setting reg_access_name or reg_access_mode in template file: ${template_name}");
2350
        }
2351
        if ( exists $reg_access_instance{$agent_name} ) {
2352
            warning_prompt("reg_access_block_instance is set without setting reg_access_name or reg_access_mode in template file: ${template_name}");
2353
        }
2354
    }
2355
 
2356
 
2357
    # Build hash of agent types indexed by agent instance name
2358
    for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) {
2359
        my $suffix = calc_suffix($i, $number_of_instances{$agent_name});
2360
        my $instance;
2361
        if ( $agent_has_env eq "NO" ) {
2362
            $instance = "m_${agent_name}${suffix}_agent";
2363
        }
2364
        else {
2365
            $instance = "m_${agent_name}_env.m_${agent_name}${suffix}_agent";
2366
        }
2367
        $agent_type_by_inst{$instance} = $agent_name;
2368
        push @agent_instance_names, $instance;
2369
    }
2370
 
2371
    if ( $agent_has_env eq "NO" ) {
2372
        push( @stand_alone_agents, $agent_name );
2373
    }
2374
    else {
2375
        push( @env_list, "${agent_name}_env" );
2376
    }
2377
 
2378
    if ( @additional_agents ) {
2379
        # Array of additional_agents
2380
        print LOGFILE "${agent_name}_env has other agents: @additional_agents\n";
2381
 
2382
        # Hash %env_agents needs to store a copy of the @additional_agents array per-agent
2383
        my @copy_array = @additional_agents;
2384
        $env_agents{"${agent_name}_env"} = \@copy_array;
2385
 
2386
        if ( $agent_has_env eq "NO" ) {
2387
          warning_prompt("Agent ${agent_name} has an additional_agent (@additional_agents) and hence should have agent_has_env = yes");
2388
        }
2389
        foreach my $extra_agent ( @additional_agents ) {
2390
            my $instance;
2391
            $instance = "m_${agent_name}_env.m_${extra_agent}_agent";
2392
            $agent_type_by_inst{$instance} = $agent_name;
2393
            push @agent_instance_names, $instance;
2394
        }
2395
    }
2396
 
2397
    if ( exists $agent_generate_methods_after_class{$agent_name} && $agent_generate_methods_after_class{$agent_name} eq "NO" )
2398
    {
2399
        if ( exists $agent_prepend_to_build_phase{$agent_name} ) {
2400
          die "ERROR in ${template_name}. agent_prepend_to_build_phase cannot be used in combination with agent_generate_methods_after_class = no";
2401
        }
2402
        if ( exists $agent_append_to_build_phase{$agent_name} ) {
2403
          die "ERROR in ${template_name}. agent_append_to_build_phase cannot be used in combination with agent_generate_methods_after_class = no";
2404
        }
2405
        if ( exists $agent_append_to_connect_phase{$agent_name} ) {
2406
          die "ERROR in ${template_name}. agent_append_to_connect_phase cannot be used in combination with agent_generate_methods_after_class = no";
2407
        }
2408
    }
2409
 
2410
    unless ( $agent_seqr_class =~ /y|yes/i ) {
2411
        if ( exists $agent_seqr_inc_before_class{$agent_name}
2412
          or exists $agent_seqr_inc_inside_class{$agent_name}
2413
          or exists $agent_seqr_inc_after_class{$agent_name} )
2414
        {
2415
          die "ERROR in ${template_name}. The sequencer_inc_before/inside/after_class include files can only be used in combination with uvm_seqr_class = yes\n";
2416
        }
2417
    }
2418
 
2419
    if ( exists $agent_env_generate_methods_after_class{$agent_name} && $agent_env_generate_methods_after_class{$agent_name} eq "NO" )
2420
    {
2421
        if ( exists $agent_env_prepend_to_build_phase{$agent_name} ) {
2422
          die "ERROR in ${template_name}. agent_env_prepend_to_build_phase cannot be used in combination with agent_env_generate_methods_after_class = no";
2423
        }
2424
        if ( exists $agent_env_append_to_build_phase{$agent_name} ) {
2425
          die "ERROR in ${template_name}. agent_env_append_to_build_phase cannot be used in combination with agent_env_generate_methods_after_class = no";
2426
        }
2427
        if ( exists $agent_env_append_to_connect_phase{$agent_name} ) {
2428
          die "ERROR in ${template_name}. agent_env_append_to_connect_phase cannot be used in combination with agent_env_generate_methods_after_class = no";
2429
        }
2430
    }
2431
}
2432
 
2433
sub check_common_pkg {
2434
    my ($fname) = @_;
2435
    if (-e "${dut_path}/${fname}" ) {
2436
        get_pkg_name("${dut_path}/${fname}");
2437
    }
2438
    else {
2439
        warning_prompt("common_pkg file ${fname} specified in ${common_tpl_fname} not found in ${dut_path}");
2440
    }
2441
}
2442
 
2443
sub get_pkg_name {
2444
    my ($fname_with_path) = @_;
2445
    my $line;
2446
    open( LFH, $fname_with_path ) or die "CANNOT OPEN FILE ${fname_with_path}!\n";
2447
    SKIP_BL: while (<LFH>) {
2448
        if (/\w+/) {
2449
            $line = $_;
2450
            last SKIP_BL;
2451
        }
2452
    }
2453
    $line or die "Exiting due to Error: common package file $fname_with_path exists but is empty\n";
2454
    FIND: while ($line) {
2455
        while ($line) {
2456
            if ( $line =~ m!\s*//.*\n! ) {    #comments - ignore
2457
                $line = <LFH>;
2458
                next FIND;
2459
            }
2460
            elsif ( $line =~ m/^\s*package\s+(\w+)\s*;/ ) {    #package declaration
2461
                $common_pkg = $1;
2462
                print LOGFILE "get_pkg_name: found package name $common_pkg\n";
2463
                last FIND;
2464
            }
2465
            $line = <LFH>;
2466
        }
2467
    }    #FIND
2468
}
2469
 
2470
sub check_common_env_pkg {
2471
    my ($fname) = @_;
2472
    if (-e "${inc_path}/${fname}" ) {
2473
        get_env_pkg_name("${inc_path}/${fname}");
2474
    }
2475
    else {
2476
        warning_prompt("common_env_pkg file ${fname} specified in ${common_tpl_fname} not found in ${inc_path}");
2477
    }
2478
}
2479
 
2480
sub get_env_pkg_name {
2481
    my ($fname_with_path) = @_;
2482
    my $line;
2483
    open( LFH, $fname_with_path ) or die "CANNOT OPEN FILE ${fname_with_path}!\n";
2484
    SKIP_BL: while (<LFH>) {
2485
        if (/\w+/) {
2486
            $line = $_;
2487
            last SKIP_BL;
2488
        }
2489
    }
2490
    $line or die "Exiting due to Error: common env package file $fname_with_path exists but is empty\n";
2491
    FIND: while ($line) {
2492
        while ($line) {
2493
            if ( $line =~ m!\s*//.*\n! ) {    #comments - ignore
2494
                $line = <LFH>;
2495
                next FIND;
2496
            }
2497
            elsif ( $line =~ m/^\s*package\s+(\w+)\s*;/ ) {    #package declaration
2498
                $common_env_pkg = $1;
2499
                print LOGFILE "get_env_pkg_name: found env package name $common_env_pkg\n";
2500
                last FIND;
2501
            }
2502
            $line = <LFH>;
2503
        }
2504
    }    #FIND
2505
}
2506
 
2507
sub extra_checking_for_additional_agents {
2508
 
2509
    foreach my $agent (@stand_alone_agents) {
2510
        push( @top_env_agents, $agent )
2511
          unless grep( /$agent/, keys(%agent_parent) );
2512
    }
2513
 
2514
    # Check for agent with agent_has_env = yes being used as an additional_agent
2515
    foreach my $agent (@agent_list) {
2516
        if ( exists $agent_parent{$agent} ) {
2517
            unless ( grep( /$agent/, @stand_alone_agents ) ) {
2518
                warning_prompt("Agent ${agent} is used as an additional_agent (in $agent_parent{$agent}) and hence should itself have agent_has_env = no");
2519
            }
2520
            if ( $number_of_instances{$agent} > 1 ) {
2521
                warning_prompt("Agent ${agent} is used as an additional_agent (in $agent_parent{$agent}) and hence should itself have number_of_instances = 1");
2522
            }
2523
        }
2524
    }
2525
}
2526
 
2527
sub calc_suffix {
2528
    my ($i, $n) = @_;
2529
    my $suffix;
2530
    if ($n == 1) { $suffix = ""; } else { $suffix = "_${i}"; }
2531
    return $suffix;
2532
}
2533
 
2534
sub check_file {
2535
    my ($fname) = @_;
2536
    unless (-e "${fname}") {
2537
        warning_prompt("SPECIFIED FILE $fname NOT FOUND");
2538
    }
2539
}
2540
 
2541
sub check_inc_file {
2542
    my ($fname) = @_;
2543
    unless (-e "${inc_path}/${fname}") {
2544
        warning_prompt("SPECIFIED INCLUDE FILE $fname NOT FOUND");
2545
    }
2546
}
2547
 
2548
sub insert_inc_file {
2549
    my ($indent, $fname, $inline, $flagname, $templatefile) = @_;
2550
    if ( defined $fname) {
2551
        my $fullname = "${project}/tb/include/${fname}";
2552
        #print "insert_inc_file, fname = ${fname}, inline = ${inline}\n";
2553
 
2554
        if (-e $fullname)
2555
        {
2556
            if (defined $inline && uc($inline) eq "INLINE")
2557
            {
2558
                open( TH, $fullname )
2559
                  || die "Exiting due to Error: can't open include file: " . $fullname . "\n";
2560
 
2561
                print FH "${indent}// Start of inlined include file $fullname\n" if $flagname ne "file_header_inc";
2562
                for ( ; ; ) {
2563
                    my $line;
2564
                    undef $!;
2565
                    unless ( defined( $line = <TH> ) ) {
2566
                        die $! if $!;
2567
                        last;    # reached EOF
2568
                    }
2569
 
2570
                    print FH $indent .$line;
2571
                }
2572
                print FH "${indent}// End of inlined include file\n" if $flagname ne "file_header_inc";
2573
                print FH "\n";
2574
            }
2575
            else
2576
            {
2577
                print FH "${indent}`include \"$fname\"\n";
2578
                print FH "\n";
2579
            }
2580
        }
2581
    }
2582
    elsif ($flagname ne "") {
2583
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
2584
            print FH "${indent}// You can insert code here by setting $flagname in file $templatefile\n\n";
2585
        }
2586
    }
2587
}
2588
 
2589
sub warning_prompt {
2590
    my $message = "@_";
2591
    warn "WARNING! $message\n";
2592
    unless ($continue_on_warning) {
2593
        print "Continue? (y/n) [n] ";
2594
        <STDIN> =~ /y/i or die "UVM CODE NOT GENERATED DUE TO ERRORS!";
2595
    }
2596
}
2597
 
2598
sub write_file_header {
2599
    my ($fname,$descript) = @_;
2600
 
2601
    my $inline = "INLINE";
2602
    insert_inc_file("", $file_header_inc, $inline, "file_header_inc", $common_tpl_fname);
2603
 
2604
    unless ( defined $generate_file_header && $generate_file_header eq "NO" )
2605
    {
2606
        print FH "//=============================================================================\n";
2607
        if ( defined $copyright ) {
2608
            print FH "// $copyright\n";
2609
            print FH "//=============================================================================\n";
2610
        }
2611
        print FH "// Project  : " . $project . "\n";
2612
        print FH "//\n";
2613
        print FH "// File Name: $fname\n";
2614
        print FH "//\n";
2615
        print FH "// Author   : Name   : $author\n"  if ( defined $author );;
2616
        print FH "//            Email  : $email\n"   if ( defined $email );
2617
        print FH "//            Tel    : $tel\n"     if ( defined $tel );
2618
        print FH "//            Dept   : $dept\n"    if ( defined $dept );
2619
        print FH "//            Company: $company\n" if ( defined $company );
2620
        print FH "//            Year   : $year\n"    if ( defined $year );
2621
        print FH "//\n";
2622
        print FH "// Version:   $version\n";
2623
        print FH "//\n";
2624
        print FH "// Code created by Easier UVM Code Generator version $VERNUM on $date\n";
2625
        print FH "//=============================================================================\n";
2626
        print FH "// Description: $descript\n";
2627
        print FH "//=============================================================================\n";
2628
        print FH "\n";
2629
    }
2630
}
2631
 
2632
 
2633
my @pp_list1;
2634
my @pp_list2;
2635
my @pp_list3;
2636
 
2637
sub align {
2638
    my ($arg1,$arg2,$arg3) = @_;
2639
    push @pp_list1, $arg1;
2640
    push @pp_list2, $arg2;
2641
    push @pp_list3, $arg3;
2642
}
2643
 
2644
sub gen_aligned {
2645
    pretty_print(\@pp_list1, \@pp_list2, \@pp_list3);
2646
    @pp_list1 = ();
2647
    @pp_list2 = ();
2648
    @pp_list3 = ();
2649
}
2650
 
2651
sub pretty_print {
2652
 
2653
# Can pretty-print 2 columns (args 1 and 2) or 3 columns (args 1, 2, and 3)
2654
# If the string in the 2nd arg is empty, the first string is printed verbatim with no \n added
2655
 
2656
    my ($arg1ref, $arg2ref, $arg3ref) = @_;
2657
    my @string1 = @{$arg1ref};
2658
    my @string2 = @{$arg2ref};
2659
    my @string3 = @{$arg3ref};
2660
    my $string1_len = @string1;
2661
    my $string2_len = @string2;
2662
    my $string3_len = @string3;
2663
 
2664
    unless ($string1_len == $string2_len and ($string2_len == $string3_len or $string3_len == 0)) {
2665
      die "Parameters to pretty_print are wrong";
2666
    }
2667
 
2668
    my $maxlen1 = 0;
2669
    for ($i = 0; $i < @string1; $i++) {
2670
      if ( length($string2[$i]) > 0 ) {
2671
          my $txt = $string1[$i];
2672
          if (length($txt) > $maxlen1) { $maxlen1 = length($txt); }
2673
      }
2674
    }
2675
 
2676
    my $maxlen2 = 0;
2677
    foreach $ele (@string2) {
2678
      if (length($ele) > $maxlen2) { $maxlen2 = length($ele); }
2679
    }
2680
 
2681
    for ($i = 0; $i < @string1; $i++) {
2682
        my $txt = $string1[$i];
2683
        print FH $txt;
2684
        if (length ($string2[$i]) > 0) {
2685
            for (1 .. $maxlen1 - length($txt)) { print FH " "; }
2686
            $txt = $string2[$i];
2687
            print FH $txt;
2688
            if ($string3_len > 0) {
2689
                for (1 .. $maxlen2 - length($txt)) { print FH " "; }
2690
                print FH $string3[$i];
2691
            }
2692
            print FH "\n";
2693
        }
2694
    }
2695
}
2696
 
2697
sub gen_if {
2698
    $dir = $project . "/tb/" . $agent_name;
2699
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_if.sv" )
2700
      || die "Exiting due to Error: can't open interface: $agent_name";
2701
 
2702
    write_file_header "${agent_name}_if.sv", "Signal interface for agent $agent_name";
2703
 
2704
    print FH "`ifndef " . uc($agent_name) . "_IF_SV\n";
2705
    print FH "`define " . uc($agent_name) . "_IF_SV\n";
2706
    print FH "\n";
2707
    print FH "interface ${agent_if}(); \n";
2708
    print FH "\n";
2709
    print FH "  timeunit      $timeunit;\n";
2710
    print FH "  timeprecision $timeprecision;\n";
2711
    print FH "\n";
2712
    print FH "  import ${common_pkg}::*;\n" if $common_pkg;
2713
    print FH "  import ${common_env_pkg}::*;\n" if $common_env_pkg;
2714
    print FH "  import ${agent_name}_pkg::*;\n";
2715
    print FH "\n";
2716
 
2717
    foreach $port_decl (@agent_port_array) {
2718
        print FH "  ${port_decl}\n";
2719
    }
2720
    print FH "\n";
2721
 
2722
    print FH "  // You can insert properties and assertions here\n";
2723
    print FH "\n";
2724
 
2725
    insert_inc_file("  ", $if_inc_inside_interface{$agent_name}, $if_inc_inside_inline{$agent_name}, "if_inc_inside_interface", $tpl_fname{$agent_name});
2726
 
2727
    print FH "endinterface : ${agent_if}\n";
2728
    print FH "\n";
2729
    print FH "`endif // " . uc($agent_name) . "_IF_SV\n";
2730
    print FH "\n";
2731
    close(FH);
2732
}    #end gen_if
2733
 
2734
sub gen_bfm {
2735
    $dir = $project . "/tb/" . $agent_name;
2736
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_bfm.sv" )
2737
      || die "Exiting due to Error: can't open interface: $agent_name";
2738
 
2739
    write_file_header "${agent_name}_bfm.sv", "Synthesizable BFM for agent $agent_name";
2740
 
2741
    print FH "`ifndef " . uc($agent_name) . "_BFM_SV\n";
2742
    print FH "`define " . uc($agent_name) . "_BFM_SV\n";
2743
    print FH "\n";
2744
 
2745
    my $interface_type;
2746
    if ( exists $byo_interface{$agent_name} ) {
2747
        $interface_type = $byo_interface{$agent_name};
2748
    }
2749
    else {
2750
        $interface_type = $agent_if;
2751
    }
2752
 
2753
    print FH "interface ${agent_name}_bfm(${interface_type} if_port); \n";
2754
    print FH "\n";
2755
    print FH "  timeunit      $timeunit;\n";
2756
    print FH "  timeprecision $timeprecision;\n";
2757
    print FH "\n";
2758
    print FH "  import ${common_pkg}::*;\n" if $common_pkg;
2759
    print FH "  import ${common_env_pkg}::*;\n" if $common_env_pkg;
2760
    print FH "  import ${agent_name}_pkg::*;\n";
2761
    print FH "\n";
2762
 
2763
    insert_inc_file("  ", $agent_inc_inside_bfm{$agent_name}, $agent_inc_inside_bfm_inline{$agent_name}, "agent_inc_inside_bfm", $tpl_fname{$agent_name});
2764
 
2765
    print FH "endinterface : ${agent_name}_bfm\n";
2766
    print FH "\n";
2767
    print FH "`endif // " . uc($agent_name) . "_BFM_SV\n";
2768
    print FH "\n";
2769
    close(FH);
2770
}    #end gen_bfm
2771
 
2772
sub gen_seq_item {
2773
    printf LOGFILE "AGENT-ITEM: $agent_item\n";
2774
    $dir = $project . "/tb/" . $agent_name;
2775
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_" . $agent_item . ".sv" )
2776
      || die "Exiting due to Error: can't open data_item: $agent_item";
2777
 
2778
    write_file_header "${agent_name}_seq_item.sv", "Sequence item for ${agent_name}_sequencer";
2779
 
2780
    print FH "`ifndef " . uc($agent_name) . "_SEQ_ITEM_SV\n";
2781
    print FH "`define " . uc($agent_name) . "_SEQ_ITEM_SV\n";
2782
    print FH "\n";
2783
 
2784
    insert_inc_file("", $agent_trans_inc_before_class{$agent_name}, $agent_trans_inc_before_inline{$agent_name}, "trans_inc_before_class", $tpl_fname{$agent_name});
2785
 
2786
    print FH "class ${agent_item} extends uvm_sequence_item; \n";
2787
    print FH "\n";
2788
    print FH "  `uvm_object_utils(" . $agent_item . ")\n";
2789
    print FH "\n";
2790
 
2791
    print FH "  // To include variables in copy, compare, print, record, pack, unpack, and compare2string, define them using trans_var in file $tpl_fname{$agent_name}\n";
2792
    print FH "  // To exclude variables from compare, pack, and unpack methods, define them using trans_meta in file $tpl_fname{$agent_name}\n";
2793
    print FH "\n";
2794
    if (@agent_var_array) {
2795
        print FH "  // Transaction variables\n";
2796
    }
2797
 
2798
    foreach my $var_decl (@agent_var_array) {
2799
        print FH "  $var_decl\n";
2800
    }
2801
    print FH "\n";
2802
 
2803
    if (@agent_meta_array) {
2804
        print FH "  // Transaction metadata\n";
2805
    }
2806
 
2807
    foreach my $var_decl (@agent_meta_array) {
2808
        print FH "  $var_decl\n";
2809
    }
2810
    print FH "\n";
2811
 
2812
    if ( @agent_var_cnstr_array ) {
2813
        my $cnstr_count = 0;
2814
        foreach my $cnstr (@agent_var_cnstr_array) {
2815
            print FH "  constraint c$cnstr_count $cnstr\n";
2816
            $cnstr_count++;
2817
        }
2818
        print FH "\n";
2819
   }
2820
    print FH "  extern function new(string name = \"\");\n";
2821
 
2822
    unless ( exists $agent_trans_generate_methods_inside_class{$agent_name} && $agent_trans_generate_methods_inside_class{$agent_name} eq "NO" )
2823
    {
2824
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
2825
            print FH "\n  // You can remove do_copy/compare/print/record and convert2string method by setting trans_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n";
2826
        }
2827
        print FH "  extern function void do_copy(uvm_object rhs);\n";
2828
        print FH "  extern function bit  do_compare(uvm_object rhs, uvm_comparer comparer);\n";
2829
        print FH "  extern function void do_print(uvm_printer printer);\n";
2830
        print FH "  extern function void do_record(uvm_recorder recorder);\n";
2831
        unless (defined $flag_nopack) {
2832
            print FH "  extern function void do_pack(uvm_packer packer);\n";
2833
            print FH "  extern function void do_unpack(uvm_packer packer);\n";
2834
        }
2835
        print FH "  extern function string convert2string();\n";
2836
    }
2837
 
2838
    print FH "\n";
2839
 
2840
    insert_inc_file("  ", $agent_trans_inc_inside_class{$agent_name}, $agent_trans_inc_inside_inline{$agent_name}, "trans_inc_inside_class", $tpl_fname{$agent_name});
2841
 
2842
    print FH "endclass : $agent_item \n";
2843
    print FH "\n";
2844
    print FH "\n";
2845
    print FH "function ${agent_item}::new(string name = \"\");\n";
2846
    print FH "  super.new(name);\n";
2847
    print FH "endfunction : new\n";
2848
    print FH "\n";
2849
    print FH "\n";
2850
 
2851
    @all_tx_vars = ();
2852
    @non_local_tx_vars = ();
2853
    @non_meta_tx_vars = ();
2854
    %enum_var_types = ();
2855
    %unpacked_bound = ();
2856
 
2857
    my $count = 1;
2858
 
2859
    PROC_VAR:foreach my $var_decl (@agent_var_array, @agent_meta_array) {
2860
        print LOGFILE "var_decl=", $var_decl, "\n";
2861
 
2862
        my $ismeta = ($count++ > @agent_var_array);
2863
 
2864
        if ( $var_decl =~ m/^const\s+/ ) {
2865
          print  "WARNING: CONSTANT TRANS_VAR $var_decl not adding to copy/compare functions!\n";
2866
          next PROC_VAR;
2867
        }
2868
        if ( $var_decl =~ m/^static\s+/ ) {
2869
          print  "WARNING: STATIC TRANS_VAR $var_decl not adding to copy/compare functions!\n";
2870
          next PROC_VAR;
2871
        }
2872
        if ( $var_decl =~ m/^typedef\s+/ ) {
2873
          print LOGFILE "Found type definition $var_decl\n";
2874
          next PROC_VAR;
2875
        }
2876
        if ( $var_decl =~ m/^constraint\s+/ ) {
2877
          print LOGFILE "Found constraint $var_decl\n";
2878
          next PROC_VAR;
2879
        }
2880
        if ( $var_decl =~ m/^\/\// ) {
2881
          print LOGFILE "Found comment $var_decl\n";
2882
          next PROC_VAR;
2883
        }
2884
 
2885
        my $islocal = ($var_decl =~ m/local|protected/);
2886
 
2887
        my $stripped_decl = $var_decl;
2888
 
2889
        $stripped_decl =~ s/\[/ \[/g;        # Insert space before [
2890
        $stripped_decl =~ s/\]/\] /g;        # Insert space after ]
2891
        $stripped_decl =~ s/\[.+?:.+?\]//g;  # Remove array bounds of the form [a:b]
2892
 
2893
        print LOGFILE "stripped_decl=", $stripped_decl, "\n";
2894
 
2895
        @fields = split /[\s]+/, $stripped_decl; #split on space
2896
 
2897
        # get name of field to print, has to work with following examples
2898
        # bit parity; // Variable is field 1 (parity)
2899
        # rand bit [Dwidth - 1:0] payload []; // Variable is field 3 (payload)
2900
        # local logic signed [3:0][7:0] vec; // Variable is field 4 (vec)
2901
        my $pf = 0;    # Type Variable is simplest case
2902
        if ( $fields[$pf] =~ m/rand|local|protected/ ) {
2903
            #starts with "rand", "local" or "protected" so skip
2904
            $pf++;
2905
        }
2906
        if ( $fields[$pf] =~ m/rand|local|protected/ ) {
2907
 
2908
            #skip "rand local", "local rand", "rand protected" or "protected rand" modifier
2909
            $pf++;
2910
        }
2911
        if ( $fields[$pf + 1] =~ m/signed|unsigned/ ) {
2912
 
2913
            #skip signed or unsigned modifier
2914
            $pf++;
2915
        }
2916
        while ( $fields[$pf] =~ m/^\d+:\d+/ ) {
2917
 
2918
            #skip packed dimensions (i.e. bit [7:0]
2919
           $pf++;
2920
        }
2921
        $pf++; # Should now point to the variable
2922
 
2923
        my $var_name =  $fields[$pf];
2924
        $var_name =~ s/;//;   #remove trailing ';'
2925
 
2926
        if ( (@fields > $pf + 1) && $fields[$pf + 1] =~ m/\[/ ) {
2927
            # Found unpacked array dimension (e.g. type var [N]
2928
            # Concatenate the remaining fields in case the unpacked range contained spaces was therefore split over multiple fields
2929
            my $parse = "";
2930
            for ($i = $pf + 1; $i < @fields; $i++) {
2931
                $parse = $parse . $fields[$i];
2932
            }
2933
            $parse =~ /\[(.+)\].*/
2934
              or die "Exiting due to Error: ran out of steam trying to parse unpacked array dimension\n";
2935
            $unpacked_bound{$var_name} = $1;
2936
        }
2937
 
2938
        push @all_tx_vars,       $var_name;
2939
        push @non_local_tx_vars, $var_name unless $islocal || $ismeta || ( exists $unpacked_bound{$var_name} );
2940
        push @non_meta_tx_vars,  $var_name unless $ismeta;
2941
 
2942
        foreach $i ( @agent_enum_array ) {
2943
            if ( $var_decl eq $i ) {
2944
                $enum_var_types{$var_name} = $fields[$pf-1];
2945
                last;
2946
            }
2947
        }
2948
 
2949
        if ( $ismeta ) {
2950
            print LOGFILE "METADATA type = $fields[$pf-1], var = $var_name\n";
2951
        }
2952
        else {
2953
            print LOGFILE "VARIABLE type = $fields[$pf-1], var = $var_name\n";
2954
        }
2955
    }
2956
 
2957
 
2958
    unless ( exists $agent_trans_generate_methods_after_class{$agent_name} && $agent_trans_generate_methods_after_class{$agent_name} eq "NO" )
2959
    {
2960
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
2961
            print FH "// You can remove do_copy/compare/print/record and convert2string method by setting trans_generate_methods_after_class = no in file $tpl_fname{$agent_name}\n\n";
2962
        }
2963
        print FH "function void ${agent_item}::do_copy(uvm_object rhs);\n";
2964
        print FH "  " . $agent_item . " rhs_;\n";
2965
        print FH "  if (!\$cast(rhs_, rhs))\n";
2966
        print FH "    `uvm_fatal(get_type_name(), \"Cast of rhs object failed\")\n";
2967
        print FH "  super.do_copy(rhs);\n";
2968
 
2969
 
2970
        foreach $field ( @all_tx_vars ) {
2971
            align("  ${field} ", "= rhs_.${field};", "");
2972
        }
2973
 
2974
        gen_aligned();
2975
 
2976
        print FH "endfunction : do_copy\n";
2977
 
2978
        print FH "\n";
2979
        print FH "\n";
2980
        print FH "function bit ${agent_item}::do_compare(uvm_object rhs, uvm_comparer comparer);\n";
2981
        print FH "  bit result;\n";
2982
        print FH "  " . $agent_item . " rhs_;\n";
2983
        print FH "  if (!\$cast(rhs_, rhs))\n";
2984
        print FH "    `uvm_fatal(get_type_name(), \"Cast of rhs object failed\")\n";
2985
        print FH "  result = super.do_compare(rhs, comparer);\n";
2986
 
2987
        foreach $field ( @non_meta_tx_vars ) {
2988
            if ( exists $unpacked_bound{$field} ) {
2989
                align("  for (int i = 0; i < $unpacked_bound{$field}; i++)\n", "", "");
2990
                align("    result &= comparer.compare_field(\"${field}\", ${field}[i], ", "rhs_.${field}[i], ", "\$bits(${field}[i]));");
2991
            }
2992
            else {
2993
                align("  result &= comparer.compare_field(\"${field}\", ${field}, ", "rhs_.${field}, ", "\$bits(${field}));");
2994
            }
2995
        }
2996
        gen_aligned();
2997
 
2998
        print FH "  return result;\n";
2999
        print FH "endfunction : do_compare\n";
3000
        print FH "\n";
3001
        print FH "\n";
3002
 
3003
        print FH "function void ${agent_item}::do_print(uvm_printer printer);\n";
3004
        print FH "  if (printer.knobs.sprint == 0)\n";
3005
        print FH "    `uvm_info(get_type_name(), convert2string(), UVM_MEDIUM)\n";
3006
        print FH "  else\n";
3007
        print FH "    printer.m_string = convert2string();\n";
3008
        print FH "endfunction : do_print\n";
3009
        print FH "\n";
3010
        print FH "\n";
3011
 
3012
        print FH "function void ${agent_item}::do_record(uvm_recorder recorder);\n";
3013
        print FH "  super.do_record(recorder);\n";
3014
        print FH "  // Use the record macros to record the item fields:\n";
3015
 
3016
        foreach $field ( @all_tx_vars ) {
3017
            if ( exists $unpacked_bound{$field} ) {
3018
                align("  for (int i = 0; i < $unpacked_bound{$field}; i++)\n", "", "");
3019
                align("    `uvm_record_field({\"${field}_\",\$sformatf(\"%0d\",i)}, ", "${field}[i])", "");
3020
            }
3021
            else {
3022
                align("  `uvm_record_field(\"${field}\", ", "${field})", "");
3023
            }
3024
        }
3025
 
3026
        gen_aligned();
3027
 
3028
        print FH "endfunction : do_record\n";
3029
        print FH "\n";
3030
        print FH "\n";
3031
 
3032
        unless (defined $flag_nopack) {
3033
            print FH "function void ${agent_item}::do_pack(uvm_packer packer);\n";
3034
            print FH "  super.do_pack(packer);\n";
3035
 
3036
            foreach $field ( @non_meta_tx_vars ) {
3037
                if ( exists $unpacked_bound{$field} ) {
3038
                    align("  `uvm_pack_sarray(${field})", " ", "");
3039
                }
3040
                elsif ( exists $enum_var_types{$field} ) {
3041
                    align("  `uvm_pack_enum(${field})", " ", "");
3042
                }
3043
                else {
3044
                    align("  `uvm_pack_int(${field})", " ", "");
3045
                }
3046
            }
3047
 
3048
            gen_aligned();
3049
 
3050
            print FH "endfunction : do_pack\n";
3051
            print FH "\n";
3052
            print FH "\n";
3053
 
3054
            print FH "function void ${agent_item}::do_unpack(uvm_packer packer);\n";
3055
            print FH "  super.do_unpack(packer);\n";
3056
 
3057
            foreach $field ( @non_meta_tx_vars ) {
3058
                if ( exists $unpacked_bound{$field} ) {
3059
                    align("  `uvm_unpack_sarray(${field})", " ", "");
3060
                }
3061
                elsif ( exists $enum_var_types{$field} ) {
3062
                    align("  `uvm_unpack_enum(${field}, ", " $enum_var_types{$field})", "");
3063
                }
3064
                else {
3065
                    align("  `uvm_unpack_int(${field})", " ", "");
3066
                }
3067
            }
3068
 
3069
            gen_aligned();
3070
 
3071
            print FH "endfunction : do_unpack\n";
3072
            print FH "\n";
3073
            print FH "\n";
3074
        }
3075
 
3076
        print FH "function string ${agent_item}::convert2string();\n";
3077
        print FH "  string s;\n";
3078
        print FH "  \$sformat(s, \"%s\\n\", super.convert2string());\n";
3079
 
3080
        if ( @all_tx_vars > 0 ) {
3081
            print FH "  \$sformat(s, {\"%s\\n\",\n";
3082
 
3083
            foreach $i ( 0 .. @all_tx_vars - 1) {
3084
                $field = $all_tx_vars[$i];
3085
                my $terminator = ( $i < @all_tx_vars - 1 ) ? "," : "},";
3086
                my $formatting = exists $unpacked_bound{$field} ? "%p" : exists $enum_var_types{$field} ? "%s" : "'h%0h  'd%0d";
3087
                align("    \"${field} ", "= ${formatting}\\n\"${terminator}", "");
3088
            }
3089
            gen_aligned();
3090
 
3091
            print FH "    get_full_name(),";
3092
            foreach $i ( 0 .. @all_tx_vars - 1) {
3093
                $field = $all_tx_vars[$i];
3094
                if ( exists $unpacked_bound{$field} ) {
3095
                    print FH " ${field}";
3096
                }
3097
                elsif ( exists $enum_var_types{$field} ) {
3098
                    print FH " ${field}.name";
3099
                }
3100
                else {
3101
                    print FH " ${field}, ${field}";
3102
                }
3103
                my $terminator = ( $i < @all_tx_vars - 1 ) ? "," : ");";
3104
                print FH "$terminator";
3105
            }
3106
        }
3107
        print FH "\n";
3108
        print FH "  return s;\n";
3109
        print FH "endfunction : convert2string\n";
3110
        print FH "\n";
3111
        print FH "\n";
3112
    }
3113
 
3114
    insert_inc_file("", $agent_trans_inc_after_class{$agent_name}, $agent_trans_inc_after_inline{$agent_name}, "trans_inc_after_class", $tpl_fname{$agent_name});
3115
 
3116
    print FH "`endif // " . uc($agent_name) . "_SEQ_ITEM_SV\n";
3117
    print FH "\n";
3118
 
3119
    close(FH);
3120
}    #end gen_data_item
3121
 
3122
sub gen_driver {
3123
    $dir = $project . "/tb/" . $agent_name;
3124
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_driver.sv" )
3125
      || die "Exiting due to Error: can't open driver: $agent_name";
3126
 
3127
    write_file_header "${agent_name}_driver.sv", "Driver for $agent_name";
3128
 
3129
    print FH "`ifndef " . uc($agent_name) . "_DRIVER_SV\n";
3130
    print FH "`define " . uc($agent_name) . "_DRIVER_SV\n";
3131
    print FH "\n";
3132
 
3133
    insert_inc_file("", $agent_driv_inc_before_class{$agent_name}, $agent_driv_inc_before_inline{$agent_name}, "driver_inc_before_class", $tpl_fname{$agent_name});
3134
 
3135
    print FH "class ${agent_name}_driver extends uvm_driver #(${agent_item});\n";
3136
    print FH "\n";
3137
    print FH "  `uvm_component_utils(" . $agent_name . "_driver)\n";
3138
    print FH "\n";
3139
 
3140
    my $interface_type;
3141
    if ( $split_transactors eq "YES" ) {
3142
      $interface_type = $agent_name . "_bfm";
3143
    }
3144
    elsif ( exists $byo_interface{$agent_name} ) {
3145
      $interface_type = $byo_interface{$agent_name};
3146
    }
3147
    else {
3148
      $interface_type = $agent_if;
3149
    }
3150
    print FH "  virtual ${interface_type} vif;\n";
3151
    print FH "\n";
3152
    print FH "  ${agent_name}_config     m_config;\n";
3153
    print FH "\n";
3154
    print FH "  extern function new(string name, uvm_component parent);\n";
3155
 
3156
    if ( exists $agent_driv_inc{$agent_name}
3157
        && -e "${project}/tb/include/$agent_driv_inc{$agent_name}" ) {
3158
        print FH "\n";
3159
        print FH "  // Methods run_phase and do_drive generated by setting driver_inc in file $tpl_fname{$agent_name}\n";
3160
        print FH "  extern task run_phase(uvm_phase phase);\n";
3161
        print FH "  extern task do_drive();\n";
3162
    }
3163
 
3164
    print FH "\n";
3165
 
3166
    insert_inc_file("  ", $agent_driv_inc_inside_class{$agent_name}, $agent_driv_inc_inside_inline{$agent_name}, "driver_inc_inside_class", $tpl_fname{$agent_name});
3167
 
3168
    print FH "endclass : " . $agent_name . "_driver \n";
3169
    print FH "\n";
3170
    print FH "\n";
3171
    print FH "function ${agent_name}_driver::new(string name, uvm_component parent);\n";
3172
    print FH "  super.new(name, parent);\n";
3173
    print FH "endfunction : new\n";
3174
    print FH "\n";
3175
    print FH "\n";
3176
 
3177
    if ( exists $agent_driv_inc{$agent_name}
3178
        && -e "${project}/tb/include/$agent_driv_inc{$agent_name}" )
3179
    {
3180
        print FH "task " . $agent_name . "_driver::run_phase(uvm_phase phase);\n";
3181
 
3182
        print FH "  `uvm_info(get_type_name(), \"run_phase\", UVM_HIGH)\n";
3183
        print FH "\n";
3184
 
3185
        print FH "  forever\n";
3186
        print FH "  begin\n";
3187
        print FH "    seq_item_port.get_next_item(req);\n";
3188
 
3189
        print FH "      `uvm_info(get_type_name(), {\"req item\\n\",req.sprint}, UVM_HIGH)\n";
3190
        print FH "    do_drive();\n";
3191
        print FH "    seq_item_port.item_done();\n";
3192
 
3193
        my $agent_clock = $agent_clock_array[0];
3194
        if ( not $agent_clock or $agent_clock eq "" ) {
3195
            print FH "    # 10ns;\n";
3196
        }
3197
        print FH "  end\n";
3198
        print FH "endtask : run_phase\n";
3199
        print FH "\n";
3200
        print FH "\n";
3201
 
3202
        insert_inc_file("", $agent_driv_inc{$agent_name}, $agent_driv_inc_inline{$agent_name}, "", "");
3203
    }
3204
 
3205
    insert_inc_file("", $agent_driv_inc_after_class{$agent_name}, $agent_driv_inc_after_inline{$agent_name}, "driver_inc_after_class", $tpl_fname{$agent_name});
3206
 
3207
    print FH "`endif // " . uc($agent_name) . "_DRIVER_SV\n";
3208
    print FH "\n";
3209
    close(FH);
3210
}
3211
 
3212
sub gen_monitor {
3213
    $dir = $project . "/tb/" . $agent_name;
3214
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_monitor.sv" )
3215
      || die "Exiting due to Error: can't open monitor: $agent_name";
3216
 
3217
    write_file_header "${agent_name}_monitor.sv", "Monitor for $agent_name";
3218
 
3219
 
3220
    print FH "`ifndef " . uc($agent_name) . "_MONITOR_SV\n";
3221
    print FH "`define " . uc($agent_name) . "_MONITOR_SV\n";
3222
    print FH "\n";
3223
 
3224
    insert_inc_file("", $agent_mon_inc_before_class{$agent_name}, $agent_mon_inc_before_inline{$agent_name}, "monitor_inc_before_class", $tpl_fname{$agent_name});
3225
 
3226
    print FH "class ${agent_name}_monitor extends uvm_monitor;\n";
3227
    print FH "\n";
3228
    print FH "  `uvm_component_utils(" . $agent_name . "_monitor)\n";
3229
    print FH "\n";
3230
 
3231
    my $interface_type;
3232
    if ( $split_transactors eq "YES" ) {
3233
      $interface_type = $agent_name . "_bfm";
3234
    }
3235
    elsif ( exists $byo_interface{$agent_name} ) {
3236
      $interface_type = $byo_interface{$agent_name};
3237
    }
3238
    else {
3239
      $interface_type = $agent_if;
3240
    }
3241
    print FH "  virtual ${interface_type} vif;\n";
3242
    print FH "\n";
3243
    print FH "  ${agent_name}_config     m_config;\n";
3244
    print FH "\n";
3245
    print FH "  uvm_analysis_port #(${agent_item}) analysis_port;\n";
3246
    print FH "\n";
3247
 
3248
    if ( exists $agent_mon_inc{$agent_name}
3249
        && -e "${project}/tb/include/$agent_mon_inc{$agent_name}" )
3250
    {
3251
        print FH "  ${agent_item} m_trans;\n";
3252
        print FH "\n";
3253
    }
3254
 
3255
    print FH "  extern function new(string name, uvm_component parent);\n";
3256
 
3257
    if ( exists $agent_mon_inc{$agent_name}
3258
        && -e "${project}/tb/include/$agent_mon_inc{$agent_name}" )
3259
    {
3260
        print FH "\n";
3261
        print FH "  // Methods run_phase, and do_mon generated by setting monitor_inc in file $tpl_fname{$agent_name}\n";
3262
        print FH "  extern task run_phase(uvm_phase phase);\n";
3263
        print FH "  extern task do_mon();\n";
3264
    }
3265
    print FH "\n";
3266
 
3267
    insert_inc_file("  ", $agent_mon_inc_inside_class{$agent_name}, $agent_mon_inc_inside_inline{$agent_name}, "monitor_inc_inside_class", $tpl_fname{$agent_name});
3268
 
3269
    print FH "endclass : " . $agent_name . "_monitor \n";
3270
    print FH "\n";
3271
    print FH "\n";
3272
    print FH "function ${agent_name}_monitor::new(string name, uvm_component parent);\n";
3273
    print FH "  super.new(name, parent);\n";
3274
    print FH "  analysis_port = new(\"analysis_port\", this);\n";
3275
    print FH "endfunction : new\n";
3276
    print FH "\n";
3277
    print FH "\n";
3278
 
3279
    if ( exists $agent_mon_inc{$agent_name}
3280
        && -e "${project}/tb/include/$agent_mon_inc{$agent_name}" )
3281
    {
3282
        print FH "task ${agent_name}_monitor::run_phase(uvm_phase phase);\n";
3283
        print FH "  `uvm_info(get_type_name(), \"run_phase\", UVM_HIGH)\n";
3284
        print FH "\n";
3285
        print FH "  m_trans = ${agent_item}::type_id::create(\"m_trans\");\n";
3286
        print FH "  do_mon();\n";
3287
        print FH "endtask : run_phase\n";
3288
        print FH "\n";
3289
        print FH "\n";
3290
 
3291
        insert_inc_file("", $agent_mon_inc{$agent_name}, $agent_mon_inc_inline{$agent_name}, "", "");
3292
    }
3293
 
3294
    insert_inc_file("", $agent_mon_inc_after_class{$agent_name}, $agent_mon_inc_after_inline{$agent_name}, "monitor_inc_after_class", $tpl_fname{$agent_name});
3295
 
3296
    print FH "`endif // " . uc($agent_name) . "_MONITOR_SV\n";
3297
    print FH "\n";
3298
    close(FH);
3299
}
3300
 
3301
sub gen_sequencer {
3302
    $dir = $project . "/tb/" . $agent_name;
3303
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_sequencer.sv" )
3304
      || die "Exiting due to Error: can't open sequencer: $agent_name";
3305
     write_file_header "${agent_name}_sequencer.sv", "Sequencer for $agent_name";
3306
 
3307
    print FH "`ifndef " . uc($agent_name) . "_SEQUENCER_SV\n";
3308
    print FH "`define " . uc($agent_name) . "_SEQUENCER_SV\n";
3309
    print FH "\n";
3310
 
3311
    if ( $agent_seqr_class =~ /y|yes/i ) {
3312
        insert_inc_file("", $agent_seqr_inc_before_class{$agent_name}, $agent_seqr_inc_before_inline{$agent_name}, "sequencer_inc_before_class", $tpl_fname{$agent_name});
3313
 
3314
        print FH "class ${agent_name}_sequencer extends uvm_sequencer #(${agent_item});\n";
3315
        print FH "\n";
3316
        print FH "  `uvm_component_utils(" . $agent_name . "_sequencer)\n";
3317
        print FH "\n";
3318
        print FH "  extern function new(string name, uvm_component parent);\n";
3319
        print FH "\n";
3320
 
3321
        insert_inc_file("  ", $agent_seqr_inc_inside_class{$agent_name}, $agent_seqr_inc_inside_inline{$agent_name}, "sequencer_inc_inside_class", $tpl_fname{$agent_name});
3322
 
3323
        print FH "endclass : " . $agent_name . "_sequencer \n";
3324
        print FH "\n";
3325
        print FH "\n";
3326
        print FH "function ${agent_name}_sequencer::new(string name, uvm_component parent);\n";
3327
        print FH "  super.new(name, parent);\n";
3328
        print FH "endfunction : new\n";
3329
        print FH "\n";
3330
        print FH "\n";
3331
 
3332
        insert_inc_file("", $agent_seqr_inc_after_class{$agent_name}, $agent_seqr_inc_after_inline{$agent_name}, "sequencer_inc_after_class", $tpl_fname{$agent_name});
3333
 
3334
        print FH "\n";
3335
        print FH "typedef ${agent_name}_sequencer ${agent_name}_sequencer_t;\n";
3336
    }
3337
    else {
3338
        print FH "// Sequencer class is specialization of uvm_sequencer\n";
3339
        print FH "typedef uvm_sequencer #("
3340
          . $agent_item . ") "
3341
          . $agent_name
3342
          . "_sequencer_t;\n";
3343
 
3344
    }
3345
    print FH "\n";
3346
    print FH "\n";
3347
    print FH "`endif // " . uc($agent_name) . "_SEQUENCER_SV\n";
3348
    print FH "\n";
3349
    close(FH);
3350
}
3351
 
3352
sub gen_config {
3353
    $dir = $project . "/tb/" . $agent_name;
3354
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_config.sv" )
3355
      || die "Exiting due to Error: can't open config: $agent_name\n";
3356
    write_file_header "${agent_name}_config.sv", "Configuration for agent $agent_name";
3357
 
3358
    print FH "`ifndef " . uc($agent_name) . "_CONFIG_SV\n";
3359
    print FH "`define " . uc($agent_name) . "_CONFIG_SV\n";
3360
    print FH "\n";
3361
 
3362
    insert_inc_file("", $agent_config_inc_before_class{$agent_name}, $agent_config_inc_before_inline{$agent_name}, "agent_config_inc_before_class", $tpl_fname{$agent_name});
3363
 
3364
    print FH "class ${agent_name}_config extends uvm_object;\n";
3365
    print FH "\n";
3366
    print FH "  // Do not register config class with the factory\n";
3367
    print FH "\n";
3368
 
3369
    my $interface_type;
3370
    if ( $split_transactors eq "YES" ) {
3371
      $interface_type = $agent_name . "_bfm";
3372
    }
3373
    elsif ( exists $byo_interface{$agent_name} ) {
3374
      $interface_type = $byo_interface{$agent_name};
3375
    }
3376
    else {
3377
      $interface_type = $agent_name . "_if";
3378
    }
3379
    align("  virtual ${interface_type} ", "vif;\n ", "");
3380
 
3381
    if ( exists $reg_access_mode{$agent_name} ) {
3382
        align("  $reg_access_block_type{$agent_name}  ", "regmodel;\n", "");
3383
    }
3384
 
3385
    align("  uvm_active_passive_enum  ", "is_active = UVM_ACTIVE;", "");
3386
    align("  bit  ", "coverage_enable;", "");
3387
    align("  bit  ", "checks_enable;", "");
3388
 
3389
    gen_aligned();
3390
 
3391
    print FH "\n";
3392
 
3393
    unless ( @config_var_array ) {
3394
        print FH "  // You can insert variables here by setting config_var in file $tpl_fname{$agent_name}\n";
3395
    }
3396
    foreach my $var_decl (@config_var_array) {
3397
        print FH "  $var_decl\n";
3398
    }
3399
    print FH "\n";
3400
 
3401
    unless ( exists $agent_config_generate_methods_inside_class{$agent_name} && $agent_config_generate_methods_inside_class{$agent_name} eq "NO" )
3402
    {
3403
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
3404
            print FH "  // You can remove new by setting agent_config_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n";
3405
        }
3406
        print FH "  extern function new(string name = \"\");\n";
3407
        print FH "\n";
3408
    }
3409
 
3410
    insert_inc_file("  ", $agent_config_inc_inside_class{$agent_name}, $agent_config_inc_inside_inline{$agent_name}, "agent_config_inc_inside_class", $tpl_fname{$agent_name});
3411
 
3412
    print FH "endclass : " . $agent_name . "_config \n";
3413
    print FH "\n";
3414
    print FH "\n";
3415
 
3416
    unless ( exists $agent_config_generate_methods_after_class{$agent_name} && $agent_config_generate_methods_after_class{$agent_name} eq "NO" )
3417
    {
3418
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
3419
            print FH "// You can remove new by setting agent_config_generate_methods_after_class = no in file $tpl_fname{$agent_name}\n\n";
3420
        }
3421
        print FH "function ${agent_name}_config::new(string name = \"\");\n";
3422
        print FH "  super.new(name);\n";
3423
        print FH "endfunction : new\n";
3424
        print FH "\n";
3425
        print FH "\n";
3426
    }
3427
 
3428
    insert_inc_file("", $agent_config_inc_after_class{$agent_name}, $agent_config_inc_after_inline{$agent_name}, "agent_config_inc_after_class", $tpl_fname{$agent_name});
3429
 
3430
    print FH "`endif // " . uc($agent_name) . "_CONFIG_SV\n";
3431
    print FH "\n";
3432
    close(FH);
3433
}
3434
 
3435
sub gen_cov {
3436
    $dir = $project . "/tb/" . $agent_name;
3437
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_coverage.sv" )
3438
      || die "Exiting due to Error: can't open coverage: $agent_name";
3439
 
3440
    write_file_header "${agent_name}_coverage.sv", "Coverage for agent $agent_name";
3441
 
3442
    print FH "`ifndef " . uc($agent_name) . "_COVERAGE_SV\n";
3443
    print FH "`define " . uc($agent_name) . "_COVERAGE_SV\n";
3444
    print FH "\n";
3445
 
3446
    insert_inc_file("", $agent_cover_inc_before_class{$agent_name}, $agent_cover_inc_before_inline{$agent_name}, "agent_cover_inc_before_class", $tpl_fname{$agent_name});
3447
 
3448
    print FH "class ${agent_name}_coverage extends uvm_subscriber #(${agent_item});\n";
3449
    print FH "\n";
3450
    print FH "  `uvm_component_utils(" . $agent_name . "_coverage)\n";
3451
    print FH "\n";
3452
 
3453
    align("  ${agent_name}_config ", "m_config;", "");
3454
    align("  bit ", "m_is_covered;", "");
3455
    align("  $agent_item ", "m_item;\n", "");
3456
    gen_aligned();
3457
 
3458
    #if include file for coverage collector exists, pull it in here, otherwise
3459
    #create covergroup and coverpoints with default bins
3460
    if ( exists $agent_cover_inc{$agent_name}
3461
        && -e "${project}/tb/include/$agent_cover_inc{$agent_name}" )
3462
    {
3463
             open(FH_COV, "<${project}/tb/include/$agent_cover_inc{$agent_name}") or die "CANNOT OPEN INCLUDE FILE agent_cover_inc{$agent_name}";
3464
            my $cov_inc = join("",<FH_COV>);
3465
            #check that file contains covergroup named "m_cov"
3466
            unless ($cov_inc =~ /covergroup\s+m_cov(\s|;)/) {
3467
                warning_prompt("COVERGROUP \"m_cov\" MUST BE DEFINED IN $agent_cover_inc{$agent_name}");
3468
        }
3469
 
3470
        insert_inc_file("  ", $agent_cover_inc{$agent_name}, $agent_cover_inc_inline{$agent_name}, "", "");
3471
    }
3472
    else {
3473
        unless ( exists $agent_cover_generate_methods_inside_class{$agent_name} && $agent_cover_generate_methods_inside_class{$agent_name} eq "NO" )
3474
        {
3475
            unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
3476
                print FH "  // You can replace covergroup m_cov by setting agent_cover_inc in file $tpl_fname{$agent_name}\n";
3477
                print FH "  // or remove covergroup m_cov by setting agent_cover_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n";
3478
            }
3479
            print FH "  covergroup m_cov;\n";
3480
            print FH "    option.per_instance = 1;\n";
3481
            print FH "    // You may insert additional coverpoints here ...\n";
3482
            print FH "\n";
3483
            foreach $field ( @non_local_tx_vars ) {
3484
#                print FH "    cp_${i}: coverpoint m_item.${tmp};\n";
3485
                print FH "    cp_${field}: coverpoint m_item.${field};\n";
3486
                print FH "    //  Add bins here if required\n";
3487
                print FH "\n";
3488
            }
3489
            print FH "  endgroup\n";
3490
            print FH "\n";
3491
        }
3492
    }
3493
 
3494
    unless ( exists $agent_cover_generate_methods_inside_class{$agent_name} && $agent_cover_generate_methods_inside_class{$agent_name} eq "NO" )
3495
    {
3496
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
3497
            print FH "  // You can remove new, write, and report_phase by setting agent_cover_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n";
3498
        }
3499
        print FH "  extern function new(string name, uvm_component parent);\n";
3500
        print FH "  extern function void write(input " . $agent_item . " t);\n";
3501
        print FH "  extern function void build_phase(uvm_phase phase);\n";
3502
        print FH "  extern function void report_phase(uvm_phase phase);\n";
3503
        print FH "\n";
3504
    }
3505
 
3506
    insert_inc_file("  ", $agent_cover_inc_inside_class{$agent_name}, $agent_cover_inc_inside_inline{$agent_name}, "agent_cover_inc_inside_class", $tpl_fname{$agent_name});
3507
 
3508
    print FH "endclass : " . $agent_name . "_coverage \n";
3509
    print FH "\n";
3510
    print FH "\n";
3511
 
3512
    unless ( exists $agent_cover_generate_methods_after_class{$agent_name} && $agent_cover_generate_methods_after_class{$agent_name} eq "NO" )
3513
    {
3514
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
3515
            print FH "// You can remove new, write, and report_phase by setting agent_cover_generate_methods_after_class = no in file $tpl_fname{$agent_name}\n\n";
3516
        }
3517
        print FH "function ${agent_name}_coverage::new(string name, uvm_component parent);\n";
3518
        print FH "  super.new(name, parent);\n";
3519
        print FH "  m_is_covered = 0;\n";
3520
        print FH "  m_cov = new();\n";
3521
        print FH "endfunction : new\n";
3522
        print FH "\n";
3523
        print FH "\n";
3524
        print FH "function void ${agent_name}_coverage::write(input ${agent_item} t);\n";
3525
        print FH "  if (m_config.coverage_enable)\n";
3526
        print FH "  begin\n";
3527
        print FH "    m_item = t;\n";
3528
        print FH "    m_cov.sample();\n";
3529
        print FH "    // Check coverage - could use m_cov.option.goal instead of 100 if your simulator supports it\n";
3530
        print FH "    if (m_cov.get_inst_coverage() >= 100) m_is_covered = 1;\n";
3531
        print FH "  end\n";
3532
        print FH "endfunction : write\n";
3533
        print FH "\n";
3534
        print FH "\n";
3535
        print FH "function void ${agent_name}_coverage::build_phase(uvm_phase phase);\n";
3536
        print FH "  if (!uvm_config_db #(${agent_name}_config)::get(this, \"\", \"config\", m_config))\n";
3537
        print FH "    `uvm_error(get_type_name(), \"${agent_name} config not found\")\n";
3538
        print FH "endfunction : build_phase\n";
3539
        print FH "\n";
3540
        print FH "\n";
3541
        print FH "function void ${agent_name}_coverage::report_phase(uvm_phase phase);\n";
3542
        print FH "  if (m_config.coverage_enable)\n";
3543
        print FH "    `uvm_info(get_type_name(), \$sformatf(\"Coverage score = %3.1f%%\", m_cov.get_inst_coverage()), UVM_MEDIUM)\n";
3544
        print FH "  else\n";
3545
        print FH "    `uvm_info(get_type_name(), \"Coverage disabled for this agent\", UVM_MEDIUM)\n";
3546
        print FH "endfunction : report_phase\n";
3547
        print FH "\n";
3548
        print FH "\n";
3549
    }
3550
 
3551
    insert_inc_file("", $agent_cover_inc_after_class{$agent_name}, $agent_cover_inc_after_inline{$agent_name}, "agent_cover_inc_after_class", $tpl_fname{$agent_name});
3552
 
3553
    print FH "`endif // " . uc($agent_name) . "_COVERAGE_SV\n";
3554
    print FH "\n";
3555
    close(FH);
3556
}
3557
 
3558
sub gen_agent {
3559
    $dir = $project . "/tb/" . $agent_name;
3560
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_agent.sv" )
3561
      || die "Exiting due to Error: can't open agent: $agent_name";
3562
 
3563
    write_file_header "${agent_name}_agent.sv", "Agent for $agent_name";
3564
 
3565
    print FH "`ifndef " . uc($agent_name) . "_AGENT_SV\n";
3566
    print FH "`define " . uc($agent_name) . "_AGENT_SV\n";
3567
    print FH "\n";
3568
 
3569
    insert_inc_file("", $agent_inc_before_class{$agent_name}, $agent_inc_before_inline{$agent_name}, "agent_inc_before_class", $tpl_fname{$agent_name});
3570
 
3571
    print FH "class ${agent_name}_agent extends uvm_agent;\n";
3572
    print FH "\n";
3573
    print FH "  `uvm_component_utils(${agent_name}_agent)\n";
3574
    print FH "\n";
3575
    print FH "  uvm_analysis_port #(${agent_item}) analysis_port;\n";
3576
    print FH "\n";
3577
    print FH "  ${agent_name}_config       m_config;\n";
3578
    print FH "  ${agent_name}_sequencer_t  m_sequencer;\n";
3579
    print FH "  ${agent_name}_driver       m_driver;\n";
3580
    print FH "  ${agent_name}_monitor      m_monitor;\n";
3581
    print FH "\n";
3582
    print FH "  local int m_is_active = -1;\n";
3583
    print FH "\n";
3584
    print FH "  extern function new(string name, uvm_component parent);\n";
3585
    print FH "\n";
3586
 
3587
    unless ( exists $agent_generate_methods_inside_class{$agent_name} && $agent_generate_methods_inside_class{$agent_name} eq "NO" )
3588
    {
3589
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
3590
            print FH "  // You can remove build/connect_phase and get_is_active by setting agent_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n";
3591
        }
3592
        print FH "  extern function void build_phase(uvm_phase phase);\n";
3593
        print FH "  extern function void connect_phase(uvm_phase phase);\n";
3594
        print FH "  extern function uvm_active_passive_enum get_is_active();\n";
3595
        print FH "\n";
3596
    }
3597
 
3598
    insert_inc_file("  ", $agent_inc_inside_class{$agent_name}, $agent_inc_inside_inline{$agent_name}, "agent_inc_inside_class", $tpl_fname{$agent_name});
3599
 
3600
    print FH "endclass : " . $agent_name . "_agent \n";
3601
    print FH "\n";
3602
    print FH "\n";
3603
 
3604
    print FH "function  ${agent_name}_agent::new(string name, uvm_component parent);\n";
3605
    print FH "  super.new(name, parent);\n";
3606
    print FH "  analysis_port = new(\"analysis_port\", this);\n";
3607
    print FH "endfunction : new\n";
3608
    print FH "\n";
3609
    print FH "\n";
3610
 
3611
    unless ( exists $agent_generate_methods_after_class{$agent_name} && $agent_generate_methods_after_class{$agent_name} eq "NO" )
3612
    {
3613
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
3614
            print FH "// You can remove build/connect_phase and get_is_active by setting agent_generate_methods_after_class = no in file $tpl_fname{$agent_name}\n\n";
3615
        }
3616
        print FH "function void ${agent_name}_agent::build_phase(uvm_phase phase);\n";
3617
        print FH "\n";
3618
 
3619
        insert_inc_file("  ", $agent_prepend_to_build_phase{$agent_name}, $agent_prepend_to_build_phase_inline{$agent_name}, "agent_prepend_to_build_phase", $tpl_fname{$agent_name});
3620
 
3621
        print FH "  if (!uvm_config_db #(${agent_name}_config)::get(this, \"\", \"config\", m_config))\n";
3622
        print FH "    `uvm_error(get_type_name(), \"${agent_name} config not found\")\n";
3623
        print FH "\n";
3624
 
3625
        print FH "  m_monitor     = ${agent_name}_monitor    ::type_id::create(\"m_monitor\", this);\n";
3626
        print FH "\n";
3627
        print FH "  if (get_is_active() == UVM_ACTIVE)\n";
3628
        print FH "  begin\n";
3629
        print FH "    m_driver    = ${agent_name}_driver     ::type_id::create(\"m_driver\", this);\n";
3630
        print FH "    m_sequencer = ${agent_name}_sequencer_t::type_id::create(\"m_sequencer\", this);\n";
3631
        print FH "  end\n";
3632
        print FH "\n";
3633
 
3634
        insert_inc_file("  ", $agent_append_to_build_phase{$agent_name}, $agent_append_to_build_phase_inline{$agent_name}, "agent_append_to_build_phase", $tpl_fname{$agent_name});
3635
 
3636
        print FH "endfunction : build_phase\n";
3637
        print FH "\n";
3638
        print FH "\n";
3639
        print FH "function void ${agent_name}_agent::connect_phase(uvm_phase phase);\n";
3640
        print FH "  if (m_config.vif == null)\n";
3641
        print FH "    `uvm_warning(get_type_name(), \"${agent_name} virtual interface is not set!\")\n";
3642
        print FH "\n";
3643
        print FH "  m_monitor.vif      = m_config.vif;\n";
3644
        print FH "  m_monitor.m_config = m_config;\n";
3645
        print FH "  m_monitor.analysis_port.connect(analysis_port);\n";
3646
        print FH "\n";
3647
        print FH "  if (get_is_active() == UVM_ACTIVE)\n";
3648
        print FH "  begin\n";
3649
        print FH "    m_driver.seq_item_port.connect(m_sequencer.seq_item_export);\n";
3650
        print FH "    m_driver.vif      = m_config.vif;\n";
3651
        print FH "    m_driver.m_config = m_config;\n";
3652
        print FH "  end\n";
3653
        print FH "\n";
3654
 
3655
        insert_inc_file("  ", $agent_append_to_connect_phase{$agent_name}, $agent_append_to_connect_phase_inline{$agent_name}, "agent_append_to_connect_phase", $tpl_fname{$agent_name});
3656
 
3657
        print FH "endfunction : connect_phase\n";
3658
        print FH "\n";
3659
        print FH "\n";
3660
        print FH "function uvm_active_passive_enum ${agent_name}_agent::get_is_active();\n";
3661
        print FH "  if (m_is_active == -1)\n";
3662
        print FH "  begin\n";
3663
        print FH "    if (uvm_config_db#(uvm_bitstream_t)::get(this, \"\", \"is_active\", m_is_active))\n";
3664
        print FH "    begin\n";
3665
        print FH "      if (m_is_active != m_config.is_active)\n";
3666
        print FH "        `uvm_warning(get_type_name(), \"is_active field in config_db conflicts with config object\")\n";
3667
        print FH "    end\n";
3668
        print FH "    else \n";
3669
        print FH "      m_is_active = m_config.is_active;\n";
3670
        print FH "  end\n";
3671
        print FH "  return uvm_active_passive_enum'(m_is_active);\n";
3672
        print FH "endfunction : get_is_active\n";
3673
        print FH "\n";
3674
        print FH "\n";
3675
    }
3676
 
3677
    insert_inc_file("", $agent_inc_after_class{$agent_name}, $agent_inc_after_inline{$agent_name}, "agent_inc_after_class", $tpl_fname{$agent_name});
3678
 
3679
    print FH "`endif // " . uc($agent_name) . "_AGENT_SV\n";
3680
    print FH "\n";
3681
    close(FH);
3682
}
3683
 
3684
sub gen_env {
3685
    $dir = $project . "/tb/" . $agent_name;
3686
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_env.sv" )
3687
      || die "Exiting due to Error: can't open env: $agent_name";
3688
 
3689
    write_file_header "${agent_name}_env.sv", "Environment for agent $agent_name";
3690
 
3691
    print FH "`ifndef " . uc($agent_name) . "_ENV_SV\n";
3692
    print FH "`define " . uc($agent_name) . "_ENV_SV\n";
3693
    print FH "\n";
3694
 
3695
    insert_inc_file("", $agent_env_inc_before_class{$agent_name}, $agent_env_inc_before_inline{$agent_name}, "agent_env_inc_before_class", $tpl_fname{$agent_name});
3696
 
3697
    print FH "class ${agent_name}_env extends uvm_env;\n";
3698
    print FH "\n";
3699
    print FH "  `uvm_component_utils(" . $agent_name . "_env)\n";
3700
    print FH "\n";
3701
    print FH "  extern function new(string name, uvm_component parent);\n";
3702
    print FH "\n";
3703
 
3704
    for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) {
3705
        my $suffix = calc_suffix($i, $number_of_instances{$agent_name});
3706
 
3707
        align("  ${agent_name}_config ", "m_${agent_name}${suffix}_config;", "");
3708
        align("  ${agent_name}_agent ", "m_${agent_name}${suffix}_agent;", "");
3709
        align("  ${agent_name}_coverage ", "m_${agent_name}${suffix}_coverage;", "");
3710
        if ( exists $reg_access_mode{$agent_name} ) {
3711
            align("  ${agent_name}_env_coverage ", "m_${agent_name}${suffix}_env_coverage;", "");
3712
            align("  $reg_access_block_type{$agent_name} ", "regmodel${suffix};  // Register model", "");
3713
            align("\n", "", "");
3714
            align("  reg2${agent_name}_adapter ", "m_reg2${agent_name}${suffix};", "");
3715
            align("  uvm_reg_predictor #($agent_item_types{$agent_name}) ", "m_${agent_name}2reg_predictor${suffix};", "");
3716
        }
3717
        align("\n", "", "");
3718
    }
3719
    gen_aligned();
3720
 
3721
    #add any other agents (%env_agents is hash of ref to array)
3722
    do {
3723
        foreach my $extra_agent ( @{ $env_agents{"${agent_name}_env"} } ) {
3724
            print LOGFILE "adding extra agent $extra_agent\n";
3725
            print FH "  ${extra_agent}_config    m_${extra_agent}_config;\n";
3726
            print FH "  ${extra_agent}_agent     m_${extra_agent}_agent;\n";
3727
            print FH "  ${extra_agent}_coverage  m_${extra_agent}_coverage;\n";
3728
            print FH "\n";
3729
        }
3730
    } if exists $env_agents{"${agent_name}_env"};
3731
 
3732
    unless ( exists $agent_env_generate_methods_inside_class{$agent_name} && $agent_env_generate_methods_inside_class{$agent_name} eq "NO" )
3733
    {
3734
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
3735
            print FH "  // You can remove build_phase and connect_phase by setting agent_env_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n";
3736
        }
3737
        print FH "  extern function void build_phase(uvm_phase phase);\n";
3738
        print FH "  extern function void connect_phase(uvm_phase phase);\n";
3739
        print FH "\n";
3740
    }
3741
 
3742
    insert_inc_file("  ", $agent_env_inc_inside_class{$agent_name}, $agent_env_inc_inside_inline{$agent_name}, "agent_env_inc_inside_class", $tpl_fname{$agent_name});
3743
 
3744
    print FH "endclass : " . $agent_name . "_env \n";
3745
    print FH "\n";
3746
    print FH "\n";
3747
    print FH "function ${agent_name}_env::new(string name, uvm_component parent);\n";
3748
    print FH "  super.new(name, parent);\n";
3749
    print FH "endfunction : new\n";
3750
    print FH "\n";
3751
    print FH "\n";
3752
 
3753
    unless ( exists $agent_env_generate_methods_after_class{$agent_name} && $agent_env_generate_methods_after_class{$agent_name} eq "NO" )
3754
    {
3755
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
3756
            print FH "// You can remove build_phase and connect_phase by setting agent_env_generate_methods_after_class = no in file $tpl_fname{$agent_name}\n\n";
3757
        }
3758
        print FH "function void ${agent_name}_env::build_phase(uvm_phase phase);\n";
3759
        print FH "\n";
3760
 
3761
        insert_inc_file("  ", $agent_env_prepend_to_build_phase{$agent_name}, $agent_env_prepend_to_build_phase_inline{$agent_name}, "agent_env_prepend_to_build_phase", $tpl_fname{$agent_name});
3762
 
3763
        for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) {
3764
            my $suffix = calc_suffix($i, $number_of_instances{$agent_name});
3765
 
3766
            if ($i > 0) { print FH "\n"; }
3767
 
3768
            print FH "  if (!uvm_config_db #(${agent_name}_config)::get(this, \"\", \"config${suffix}\", m_${agent_name}${suffix}_config))\n";
3769
            print FH "    `uvm_error(get_type_name(), \"Unable to get config from configuration database\")\n";
3770
            print FH "  regmodel${suffix} = m_${agent_name}${suffix}_config.regmodel;\n" if exists $reg_access_mode{$agent_name};
3771
            print FH "\n";
3772
            print FH "  uvm_config_db #(${agent_name}_config)::set(this, \"m_${agent_name}${suffix}_agent\", \"config\", m_${agent_name}${suffix}_config);\n";
3773
            print FH "  if (m_${agent_name}${suffix}_config.is_active == UVM_ACTIVE )\n";
3774
            print FH "    uvm_config_db #(${agent_name}_config)::set(this, \"m_${agent_name}${suffix}_agent.m_sequencer\", \"config\", m_${agent_name}${suffix}_config);\n";
3775
            print FH "  uvm_config_db #(${agent_name}_config)::set(this, \"m_${agent_name}${suffix}_coverage\", \"config\", m_${agent_name}${suffix}_config);\n";
3776
            if ( exists $reg_access_mode{$agent_name} ) {
3777
                print FH "  uvm_config_db #(${agent_name}_config)::set(this, \"m_${agent_name}${suffix}_env_coverage\", \"config\", m_${agent_name}${suffix}_config);\n";
3778
            }
3779
            print FH "\n";
3780
            print FH "  m_${agent_name}${suffix}_agent    = ${agent_name}_agent   ::type_id::create(\"m_${agent_name}${suffix}_agent\", this);\n";
3781
            print FH "\n";
3782
            print FH "  m_${agent_name}${suffix}_coverage = ${agent_name}_coverage::type_id::create(\"m_${agent_name}${suffix}_coverage\", this);\n";
3783
            if ( exists $reg_access_mode{$agent_name} ) {
3784
                print FH "  m_${agent_name}${suffix}_env_coverage  = ${agent_name}_env_coverage::type_id::create(\"m_${agent_name}${suffix}_env_coverage\", this);\n";
3785
                print FH "  m_reg2${agent_name}${suffix}           = reg2${agent_name}_adapter ::type_id::create(\"m_reg2${agent_name}${suffix}\", this);\n";
3786
                print FH "\n";
3787
                print FH "  m_${agent_name}2reg_predictor${suffix} = ";
3788
                print FH "uvm_reg_predictor #($agent_item_types{$agent_name})::type_id::create(\"m_${agent_name}2reg_predictor${suffix}\", this);\n";
3789
            }
3790
        }
3791
 
3792
        do {
3793
            print FH "\n";
3794
            print FH "  // Additional agents";
3795
            foreach my $extra_agent ( @{ $env_agents{"${agent_name}_env"} } ) {
3796
                print FH "\n";
3797
                print FH "  if (!uvm_config_db #(${extra_agent}_config)::get(this, \"\", \"config\", m_${extra_agent}_config))\n";
3798
                print FH "    `uvm_error(get_type_name(), \"Unable to get ${extra_agent}_config from configuration database\")\n";
3799
                print FH "\n";
3800
                print FH "  uvm_config_db #(${extra_agent}_config)::set(this, \"m_${extra_agent}_agent\", \"config\",  m_${extra_agent}_config);\n";
3801
                print FH "  if (m_${extra_agent}_config.is_active == UVM_ACTIVE )\n";
3802
                print FH "    uvm_config_db #(${extra_agent}_config)::set(this, \"m_${extra_agent}_agent.m_sequencer\", \"config\",  m_${extra_agent}_config);\n";
3803
                print FH "  uvm_config_db #(${extra_agent}_config)::set(this, \"m_${extra_agent}_coverage\", \"config\",  m_${extra_agent}_config);\n";
3804
                print FH "\n";
3805
                print FH "  m_${extra_agent}_agent    = ${extra_agent}_agent   ::type_id::create(\"m_${extra_agent}_agent\", this);\n";
3806
                print FH "  m_${extra_agent}_coverage = ${extra_agent}_coverage::type_id::create(\"m_${extra_agent}_coverage\", this);\n";
3807
            }
3808
        } if exists $env_agents{"${agent_name}_env"};
3809
        print FH "\n";
3810
 
3811
        insert_inc_file("  ", $agent_env_append_to_build_phase{$agent_name}, $agent_env_append_to_build_phase_inline{$agent_name}, "agent_env_append_to_build_phase", $tpl_fname{$agent_name});
3812
 
3813
        print FH "endfunction : build_phase\n";
3814
        print FH "\n";
3815
        print FH "\n";
3816
 
3817
        print FH "function void ${agent_name}_env::connect_phase(uvm_phase phase);\n";
3818
        print FH "\n";
3819
 
3820
        for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) {
3821
            my $suffix = calc_suffix($i, $number_of_instances{$agent_name});
3822
 
3823
            align("  m_${agent_name}${suffix}_agent", ".analysis_port.connect(m_${agent_name}${suffix}_coverage.analysis_export);\n", "");
3824
 
3825
             if ( exists $reg_access_mode{$agent_name} ) {
3826
                align("  m_${agent_name}${suffix}_agent", ".analysis_port.connect(m_${agent_name}2reg_predictor${suffix}.bus_in);\n", "");
3827
                align("  m_${agent_name}${suffix}_agent", ".analysis_port.connect(m_${agent_name}${suffix}_env_coverage.analysis_export);\n", "");
3828
                align("  m_${agent_name}${suffix}_env_coverage.regmodel = regmodel${suffix};\n", "", "");
3829
            }
3830
        }
3831
 
3832
        do {
3833
            foreach my $extra_agent ( @{ $env_agents{"${agent_name}_env"} } ) {
3834
                align("  m_${extra_agent}_agent", ".analysis_port.connect(m_${extra_agent}_coverage.analysis_export);", "");
3835
            }
3836
        } if exists $env_agents{"${agent_name}_env"};
3837
 
3838
        gen_aligned();
3839
 
3840
        print FH "\n";
3841
 
3842
        insert_inc_file("  ", $agent_env_append_to_connect_phase{$agent_name}, $agent_env_append_to_connect_phase_inline{$agent_name}, "agent_env_append_to_connect_phase", $tpl_fname{$agent_name});
3843
 
3844
        print FH "endfunction : connect_phase\n";
3845
        print FH "\n";
3846
        print FH "\n";
3847
    }
3848
 
3849
    insert_inc_file("", $agent_env_inc_after_class{$agent_name}, $agent_env_inc_after_inline{$agent_name}, "agent_env_inc_after_class", $tpl_fname{$agent_name});
3850
 
3851
    print FH "`endif // " . uc($agent_name) . "_ENV_SV\n";
3852
    print FH "\n";
3853
    close(FH);
3854
}
3855
 
3856
sub gen_seq_lib {
3857
    $dir = $project . "/tb/" . $agent_name;
3858
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_seq_lib.sv" )
3859
      || die "Exiting due to Error: can't open seq_lib: $agent_name";
3860
 
3861
    write_file_header "${agent_name}_seq_lib.sv", "Sequence for agent $agent_name";
3862
 
3863
    print FH "`ifndef " . uc($agent_name) . "_SEQ_LIB_SV\n";
3864
    print FH "`define " . uc($agent_name) . "_SEQ_LIB_SV\n";
3865
    print FH "\n";
3866
 
3867
    print FH "class ${agent_name}_default_seq extends uvm_sequence #($agent_item);\n";
3868
    print FH "\n";
3869
    print FH "  `uvm_object_utils(" . $agent_name . "_default_seq)\n";
3870
    print FH "\n";
3871
 
3872
    print FH "  ${agent_name}_config  m_config;\n";
3873
    print FH "\n";
3874
    print FH "  extern function new(string name = \"\");\n";
3875
    print FH "  extern task body();\n";
3876
    print FH "\n";
3877
    print FH "`ifndef UVM_POST_VERSION_1_1\n";
3878
    print FH "  // Functions to support UVM 1.2 objection API in UVM 1.1\n";
3879
    print FH "  extern function uvm_phase get_starting_phase();\n";
3880
    print FH "  extern function void set_starting_phase(uvm_phase phase);\n";
3881
    print FH "`endif\n";
3882
    print FH "\n";
3883
    print FH "endclass : " . $agent_name . "_default_seq\n";
3884
    print FH "\n";
3885
    print FH "\n";
3886
    print FH "function ${agent_name}_default_seq::new(string name = \"\");\n";
3887
    print FH "  super.new(name);\n";
3888
    print FH "endfunction : new\n";
3889
    print FH "\n";
3890
    print FH "\n";
3891
    print FH "task ${agent_name}_default_seq::body();\n";
3892
    print FH "  `uvm_info(get_type_name(), \"Default sequence starting\", UVM_HIGH)\n";
3893
    print FH "\n";
3894
    print FH "  req = " . $agent_item . "::type_id::create(\"req\");\n";
3895
    print FH "  start_item(req); \n";
3896
    print FH "  if ( !req.randomize() )\n";
3897
    print FH "    `uvm_error(get_type_name(), \"Failed to randomize transaction\")\n";
3898
    print FH "  finish_item(req); \n";
3899
    print FH "\n";
3900
    print FH "  `uvm_info(get_type_name(), \"Default sequence completed\", UVM_HIGH)\n";
3901
    print FH "endtask : body\n";
3902
    print FH "\n";
3903
    print FH "\n";
3904
    print FH "`ifndef UVM_POST_VERSION_1_1\n";
3905
    print FH "function uvm_phase ${agent_name}_default_seq::get_starting_phase();\n";
3906
    print FH "  return starting_phase;\n";
3907
    print FH "endfunction: get_starting_phase\n";
3908
    print FH "\n";
3909
    print FH "\n";
3910
    print FH "function void ${agent_name}_default_seq::set_starting_phase(uvm_phase phase);\n";
3911
    print FH "  starting_phase = phase;\n";
3912
    print FH "endfunction: set_starting_phase\n";
3913
    print FH "`endif\n";
3914
    print FH "\n";
3915
    print FH "\n";
3916
 
3917
    insert_inc_file("", $agent_seq_inc{$agent_name}, $agent_seq_inc_inline{$agent_name}, "agent_seq_inc", $tpl_fname{$agent_name});
3918
 
3919
    print FH "`endif // " . uc($agent_name) . "_SEQ_LIB_SV\n";
3920
    print FH "\n";
3921
 
3922
    close(FH);
3923
}
3924
 
3925
sub gen_env_seq_lib {
3926
    $dir = $project . "/tb/" . $agent_name;
3927
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_env_seq_lib.sv" )
3928
      || die "Exiting due to Error: can't open env_seq_lib: $agent_name";
3929
 
3930
    write_file_header "${agent_name}_env_seq_lib.sv", "Sequence for $agent_name";
3931
 
3932
    print FH "`ifndef " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n";
3933
    print FH "`define " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n";
3934
    print FH "\n";
3935
 
3936
    print FH "class ${agent_name}_env_default_seq extends uvm_sequence #(uvm_sequence_item);\n";
3937
    print FH "\n";
3938
    print FH "  `uvm_object_utils(" . $agent_name . "_env_default_seq)\n";
3939
    print FH "\n";
3940
    print FH "  ${agent_name}_env m_env;\n";
3941
    print FH "\n";
3942
    print FH "  extern function new(string name = \"\");\n";
3943
    print FH "  extern task body();\n";
3944
    print FH "\n";
3945
    print FH "`ifndef UVM_POST_VERSION_1_1\n";
3946
    print FH "  // Functions to support UVM 1.2 objection API in UVM 1.1\n";
3947
    print FH "  extern function uvm_phase get_starting_phase();\n";
3948
    print FH "  extern function void set_starting_phase(uvm_phase phase);\n";
3949
    print FH "`endif\n";
3950
    print FH "\n";
3951
    print FH "endclass : " . $agent_name . "_env_default_seq\n";
3952
    print FH "\n";
3953
    print FH "\n";
3954
    print FH "function  ${agent_name}_env_default_seq::new(string name = \"\");\n";
3955
    print FH "  super.new(name);\n";
3956
    print FH "endfunction : new\n";
3957
    print FH "\n";
3958
    print FH "\n";
3959
    print FH "task ${agent_name}_env_default_seq::body();\n";
3960
    print FH "  `uvm_info(get_type_name(), \"Default sequence starting\", UVM_HIGH)\n";
3961
    print FH "\n";
3962
 
3963
    print FH
3964
      "  // Note: there can be multiple child sequences started concurrently within this fork..join\n";
3965
    print FH "  fork\n";
3966
 
3967
    for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) {
3968
        my $suffix = calc_suffix($i, $number_of_instances{$agent_name});
3969
        my $sequencer_instance_name = "m_env.m_${agent_name}${suffix}_agent.m_sequencer";
3970
 
3971
        if ( $i > 0 ) { print FH "\n"; }
3972
 
3973
        print FH "    if (m_env.m_${agent_name}${suffix}_config.is_active == UVM_ACTIVE)\n";
3974
        print FH "    begin\n";
3975
        print FH "      ${agent_name}_default_seq seq;\n";
3976
        print FH "      seq = ${agent_name}_default_seq::type_id::create(\"seq${suffix}\");\n";
3977
        print FH "      seq.set_item_context(this, ${sequencer_instance_name});\n";
3978
        print FH "      if ( !seq.randomize() )\n";
3979
        print FH "        `uvm_error(get_type_name(), \"Failed to randomize sequence\")\n";
3980
        print FH "      seq.m_config = m_env.m_${agent_name}${suffix}_config;\n";
3981
        print FH "      seq.set_starting_phase( get_starting_phase() );\n";
3982
        print FH "      seq.start(${sequencer_instance_name}, this);\n";
3983
        print FH "    end\n";
3984
 
3985
    }
3986
 
3987
    foreach my $extra_agent ( @{ $env_agents{"${agent_name}_env"} } ) {
3988
        my $sequencer_instance_name = "m_env.m_${extra_agent}_agent.m_sequencer";
3989
 
3990
        print FH "\n";
3991
        print FH "    if (m_env.m_${extra_agent}_agent.m_config.is_active == UVM_ACTIVE)\n";
3992
        print FH "    begin\n";
3993
        print FH "      ${extra_agent}_default_seq seq;\n";
3994
        print FH "      seq = ${extra_agent}_default_seq::type_id::create(\"seq\");\n";
3995
        print FH "      seq.set_item_context(this, ${sequencer_instance_name});\n";
3996
        print FH "      if ( !seq.randomize() )\n";
3997
        print FH "        `uvm_error(get_type_name(), \"Failed to randomize sequence\")\n";
3998
        print FH "      seq.m_config = m_env.m_${extra_agent}_agent.m_config;\n";
3999
        print FH "      seq.set_starting_phase( get_starting_phase() );\n";
4000
        print FH "      seq.start(${sequencer_instance_name}, this);\n";
4001
        print FH "    end\n";
4002
    }
4003
    print FH "  join\n";
4004
    print FH "\n";
4005
    print FH "  `uvm_info(get_type_name(), \"Default sequence completed\", UVM_HIGH)\n";
4006
    print FH "endtask : body\n";
4007
 
4008
    print FH "\n";
4009
    print FH "\n";
4010
    print FH "`ifndef UVM_POST_VERSION_1_1\n";
4011
    print FH "function uvm_phase ${agent_name}_env_default_seq::get_starting_phase();\n";
4012
    print FH "  return starting_phase;\n";
4013
    print FH "endfunction: get_starting_phase\n";
4014
    print FH "\n";
4015
    print FH "\n";
4016
    print FH "function void ${agent_name}_env_default_seq::set_starting_phase(uvm_phase phase);\n";
4017
    print FH "  starting_phase = phase;\n";
4018
    print FH "endfunction: set_starting_phase\n";
4019
    print FH "`endif\n";
4020
    print FH "\n";
4021
    print FH "\n";
4022
 
4023
    insert_inc_file("", $agent_env_seq_inc{$agent_name}, $agent_env_seq_inc_inline{$agent_name}, "agent_env_seq_inc", $tpl_fname{$agent_name});
4024
 
4025
    print FH "`endif // " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n";
4026
    print FH "\n";
4027
 
4028
    close(FH);
4029
}
4030
 
4031
sub gen_agent_pkg {
4032
 
4033
    ### file list for files in sv directoru (.svh file)
4034
    $dir = $project . "/tb/" . $agent_name;
4035
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_pkg.sv" )
4036
      || die "Exiting due to Error: can't open include file: $agent_name";
4037
 
4038
    write_file_header "${agent_name}_pkg.sv", "Package for agent $agent_name";
4039
 
4040
    print FH "package ${agent_name}_pkg;\n";
4041
    print FH "\n";
4042
    print FH "  `include \"uvm_macros.svh\"\n";
4043
    print FH "\n";
4044
    print FH "  import uvm_pkg::*;\n";
4045
    print FH "\n";
4046
    print FH "  import ${common_pkg}::*;\n" if $common_pkg;
4047
    print FH "  import ${common_env_pkg}::*;\n" if $common_env_pkg;
4048
    print FH "  import regmodel_pkg::*;\n" if exists $reg_access_mode{$agent_name};
4049
    do {
4050
        foreach my $extra_agent ( @{ $env_agents{"${agent_name}_env"} } ) {
4051
            print FH "  import ${extra_agent}_pkg::*;\n";
4052
        }
4053
    } if exists $env_agents{"${agent_name}_env"};
4054
    print FH "\n";
4055
    print FH "  `include \"${agent_name}_${agent_item}.sv\"\n";
4056
 
4057
    print FH "  `include \"" . $agent_name . "_config.sv\"\n";
4058
    print FH "  `include \"" . $agent_name . "_driver.sv\"\n";
4059
    print FH "  `include \"" . $agent_name . "_monitor.sv\"\n";
4060
    print FH "  `include \"" . $agent_name . "_sequencer.sv\"\n";
4061
    print FH "  `include \"" . $agent_name . "_coverage.sv\"\n";
4062
    print FH "  `include \"" . $agent_name . "_agent.sv\"\n";
4063
    print FH "  `include \"" . $agent_name . "_seq_lib.sv\"\n";
4064
    if ( exists $reg_access_mode{$agent_name} ) {
4065
        print FH "  `include \"reg2" . $agent_name . "_adapter.sv\"\n";
4066
        print FH "  `include \"" . $agent_name . "_env_coverage.sv\"\n";
4067
    }
4068
    do {
4069
        print FH "  `include \"" . $agent_name . "_env.sv\"\n";
4070
        print FH "  `include \"" . $agent_name . "_env_seq_lib.sv\"\n";
4071
    } unless $agent_has_env eq "NO";
4072
    print FH "\n";
4073
    print FH "endpackage : ${agent_name}_pkg\n";
4074
    close(FH);
4075
}
4076
 
4077
sub gen_top_pkg {
4078
 
4079
    ### file list for files in sv directoru (.svh file)
4080
    $dir = $project . "/tb/" . $tbname;
4081
    open( FH, ">" . $dir . "/sv/" . $tbname . "_pkg.sv" )
4082
      || die "Exiting due to Error: can't open include file: $tbname";
4083
 
4084
    write_file_header "${tbname}_pkg.sv", "Package for $tbname";
4085
 
4086
    print FH "package " . $tbname . "_pkg;\n";
4087
    print FH "\n";
4088
    print FH "  `include \"uvm_macros.svh\"\n";
4089
    print FH "\n";
4090
    print FH "  import uvm_pkg::*;\n";
4091
    print FH "\n";
4092
    print FH "  import regmodel_pkg::*;\n" if $regmodel;
4093
    print FH "  import ${common_pkg}::*;\n" if $common_pkg;
4094
    print FH "  import ${common_env_pkg}::*;\n" if $common_env_pkg;
4095
 
4096
    foreach my $agent (@agent_list) {
4097
        print FH "  import ${agent}_pkg::*;\n";
4098
    }
4099
 
4100
    print FH "\n";
4101
    print FH "  `include \"" . $tbname . "_config.sv\"\n";
4102
    print FH "  `include \"" . $tbname . "_seq_lib.sv\"\n";
4103
 
4104
    if ( keys %ref_model ) {
4105
        print FH "  `include \"port_converter.sv\"\n";
4106
    }
4107
 
4108
    foreach my $ref_model_name ( keys(%ref_model) ) {
4109
        print FH "  `include \"$ref_model_name.sv\"\n";
4110
    }
4111
 
4112
    print FH "  `include \"" . $tbname . "_env.sv\"\n";
4113
    print FH "\n";
4114
    print FH "endpackage : " . $tbname . "_pkg\n";
4115
    print FH "\n";
4116
    close(FH);
4117
}
4118
 
4119
sub gen_dut_inst() {
4120
    my $port_list_file = $dut_pfile;
4121
    open( PFH, $port_list_file )
4122
      or die "Exiting due to Error: can't open template: ${port_list_file}\n";
4123
 
4124
    #skip empty lines
4125
    my $line = "";
4126
  SKIP_BL: while (<PFH>) {
4127
        if (/\w+/) {
4128
            $line = $_;
4129
            last SKIP_BL;
4130
        }
4131
    }
4132
    $line
4133
      or die "Exiting due to Error: dut_pfile $dut_pfile exists but is empty\n";
4134
    my $if_name  = $1;
4135
 
4136
    my @param_list1;
4137
    my @param_list2;
4138
    my @param_list3;
4139
 
4140
    my @port_list1;
4141
    my @port_list2;
4142
    my @port_list3;
4143
 
4144
    my $count_of_trailing_comments = 0;
4145
 
4146
  XPROC_INTF: while ($line) {
4147
        if ($if_name) {
4148
# The name in the pinlist file was originally an interface name but can now be a user-defined interface instance name instead
4149
            if ( exists $if_instance_names{$if_name} ) {
4150
              $if_name = $if_instance_names{$if_name};
4151
            }
4152
            print LOGFILE "Writing ports for interface $if_name\n";
4153
        }
4154
 
4155
        while ($line) {
4156
            if ( $line =~ m/\s*#/ ) {    #script comments - ignore
4157
                $line = <PFH>;
4158
                next XPROC_INTF;
4159
            }
4160
            elsif ( $line =~ m!^\s*//.*\n! ) {    #SV comments
4161
                 push @port_list1, "    $&";
4162
                 push @port_list2, "";
4163
                 $count_of_trailing_comments++;
4164
            }
4165
            elsif ( $line =~ m/^\s*PAR\s*(\||\=)\s*(\S+)\s+(\S+)\n/ ) {    #parameters
4166
                push @param_list1, "    .$2";
4167
                push @param_list2, "($3),";
4168
            }
4169
            elsif ( $line =~ /^\s*(\S+)\s+(\S+)\s*\n/ ) {    #ports
4170
                if ($if_name) {
4171
                    push @port_list1, "    .$1";
4172
                    push @port_list2, "($if_name.$2),";
4173
                }
4174
                else {
4175
                    push @port_list1, "    .$1";
4176
                    push @port_list2, "($2),";
4177
                }
4178
                $count_of_trailing_comments = 0;
4179
            }
4180
            elsif ( $line =~ /\s*DEC\s*(\||\=)\s*(.+)\s*\n/ ) {    #variable dec
4181
                print FH "  $2\n";
4182
            }
4183
            elsif ( $line =~ /!(\w+){0,1}/ ) {                #next if_name
4184
                $if_name = ( $1 and $1 ne "none" ) ? $1 : "";
4185
                $line = <PFH>;
4186
                next XPROC_INTF;
4187
            }
4188
            $line = <PFH>;
4189
        }
4190
    }    #XPROC_INTF
4191
 
4192
    print FH "  $dut_top ";
4193
    if (@param_list1) {
4194
        chop($param_list2[-1]);  #remove trailing ','
4195
        print FH "#(\n";
4196
        pretty_print(\@param_list1, \@param_list2, \@param_list3);
4197
        print FH "  )\n  ";
4198
    }
4199
    print FH "${dut_iname} (\n";
4200
    if (@port_list2) { chop($port_list2[-1-$count_of_trailing_comments]); }    #remove trailing ','
4201
    pretty_print(\@port_list1, \@port_list2, \@port_list3);
4202
    print FH "  );\n";
4203
}
4204
 
4205
 
4206
sub gen_top_env {
4207
    $dir = $project . "/tb/" . $tbname;
4208
    open( FH, ">" . $dir . "/sv/" . $tbname . "_env.sv" )
4209
      || die "Exiting due to Error: can't open env: $tbname";
4210
 
4211
    write_file_header "${tbname}_env.sv", "Environment for $tbname";
4212
 
4213
    print FH "`ifndef " . uc($tbname) . "_ENV_SV\n";
4214
    print FH "`define " . uc($tbname) . "_ENV_SV\n";
4215
    print FH "\n";
4216
 
4217
    insert_inc_file("", $top_env_inc_before_class, $top_env_inc_before_inline, "top_env_inc_before_class", $common_tpl_fname);
4218
 
4219
    if ( keys %ref_model ) {
4220
        print FH "import pk_syoscb::*;\n";
4221
        print FH "\n";
4222
    }
4223
 
4224
    print FH "class ${tbname}_env extends uvm_env;\n";
4225
    print FH "\n";
4226
    print FH "  `uvm_component_utils(" . $tbname . "_env)\n";
4227
    print FH "\n";
4228
    print FH "  extern function new(string name, uvm_component parent);\n";
4229
    print FH "\n";
4230
 
4231
    if ( keys %ref_model ) {
4232
        print FH "  // Reference model and Syosil scoreboard\n";
4233
    }
4234
    foreach my $ref_model_name ( keys(%ref_model) ) {
4235
        #foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) {
4236
        #    $agent_name = ${agent_type_by_inst{$input}};
4237
        #    my $name = $input;
4238
        #    $name =~ s/\./__/g;
4239
        #    align("  typedef port_converter #($agent_item_types{$agent_name}) ", "converter_${name}_t;", "");
4240
        #}
4241
        foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) {
4242
            $agent_name = ${agent_type_by_inst{$output}};
4243
            my $name = $output;
4244
            $name =~ s/\./__/g;
4245
            align("  typedef port_converter #($agent_item_types{$agent_name}) ", "converter_${name}_t;", "");
4246
        }
4247
    }
4248
    gen_aligned();
4249
    print FH "\n";
4250
 
4251
    foreach my $ref_model_name ( keys(%ref_model) ) {
4252
 
4253
        #foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) {
4254
        #    my $name = $input;
4255
        #    $name =~ s/\./__/g;
4256
        #    align("  converter_${name}_t ", "m_converter_${name};", "");
4257
        #}
4258
        foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) {
4259
            my $name = $output;
4260
            $name =~ s/\./__/g;
4261
            align("  converter_${name}_t ", "m_converter_${name};", "");
4262
        }
4263
 
4264
        align("\n", "", "");
4265
        align("  $ref_model_name ", "m_${ref_model_name};", "");
4266
        align("  cl_syoscb ", "m_${ref_model_name}_scoreboard;", "");
4267
        align("  cl_syoscb_cfg ", "m_${ref_model_name}_config;", "");
4268
        align("\n", "", "");
4269
    }
4270
    gen_aligned();
4271
 
4272
    print FH "  // Child environments\n" if @env_list;
4273
 
4274
    foreach my $agent_env (@env_list) {
4275
        align("  ${agent_env}  ", "m_${agent_env};", "");
4276
    }
4277
    align("\n", "", "") if @env_list;
4278
 
4279
    foreach my $agent (@agent_list) {
4280
 
4281
        for ( my $i = 0 ; $i < $number_of_instances{$agent} ; $i++ ) {
4282
            my $suffix = calc_suffix($i, $number_of_instances{$agent});
4283
 
4284
            do {
4285
                align("  ${agent}_config  ", "m_${agent}${suffix}_config;", "");
4286
            } unless grep( /$agent/, @top_env_agents );
4287
        }
4288
    }
4289
 
4290
    align("\n", "", "") if @env_list;
4291
    align("  // Child agents\n", "", "") if @top_env_agents;
4292
 
4293
    foreach $aname (@top_env_agents) {
4294
 
4295
        for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) {
4296
            my $suffix = calc_suffix($i, $number_of_instances{$aname});
4297
 
4298
                align("  ${aname}_config  ", "m_${aname}${suffix}_config;", "");
4299
                align("  ${aname}_agent  ", "m_${aname}${suffix}_agent;", "");
4300
                align("  ${aname}_coverage  ", "m_${aname}${suffix}_coverage;", "");
4301
                align("\n", "", "");
4302
        }
4303
    }
4304
 
4305
    if ( $regmodel ) {
4306
                align("  // Register model\n", "", "");
4307
                align("  $top_reg_block_type  ", "regmodel;", "");
4308
    }
4309
 
4310
    align("  ${tbname}_config ", "m_config;\n", "");
4311
 
4312
    gen_aligned();
4313
 
4314
    unless ( defined $top_env_generate_methods_inside_class && $top_env_generate_methods_inside_class eq "NO" )
4315
    {
4316
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
4317
            print FH "  // You can remove build/connect/run_phase by setting top_env_generate_methods_inside_class = no in file ${common_tpl_fname}\n\n";
4318
        }
4319
        print FH "  extern function void build_phase(uvm_phase phase);\n";
4320
        print FH "  extern function void connect_phase(uvm_phase phase);\n";
4321
        unless ( defined $top_env_generate_end_of_elaboration && $top_env_generate_end_of_elaboration eq "NO" )
4322
        {
4323
            print FH "  extern function void end_of_elaboration_phase(uvm_phase phase);\n";
4324
        }
4325
        unless ( defined $top_env_generate_run_phase && $top_env_generate_run_phase eq "NO" )
4326
        {
4327
            print FH "  extern task          run_phase(uvm_phase phase);\n";
4328
        }
4329
        print FH "\n";
4330
    }
4331
 
4332
    insert_inc_file("  ", $top_env_inc_inside_class, $top_env_inc_inside_inline, "top_env_inc_inside_class", $common_tpl_fname);
4333
 
4334
    print FH "endclass : " . $tbname . "_env \n";
4335
    print FH "\n";
4336
    print FH "\n";
4337
    print FH "function ${tbname}_env::new(string name, uvm_component parent);\n";
4338
    print FH "  super.new(name, parent);\n";
4339
    print FH "endfunction : new\n";
4340
    print FH "\n";
4341
    print FH "\n";
4342
 
4343
    unless ( defined $top_env_generate_methods_after_class && $top_env_generate_methods_after_class eq "NO" )
4344
    {
4345
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
4346
            print FH "// You can remove build/connect/run_phase by setting top_env_generate_methods_after_class = no in file ${common_tpl_fname}\n\n";
4347
        }
4348
        print FH "function void ${tbname}_env::build_phase(uvm_phase phase);\n";
4349
        print FH "  `uvm_info(get_type_name(), \"In build_phase\", UVM_HIGH)\n";
4350
        print FH "\n";
4351
 
4352
        insert_inc_file("  ", $top_env_prepend_to_build_phase, $top_env_prepend_to_build_phase_inline, "top_env_prepend_to_build_phase", $common_tpl_fname);
4353
 
4354
        print FH "  if (!uvm_config_db #(${tbname}_config)::get(this, \"\", \"config\", m_config)) \n";
4355
        print FH "    `uvm_error(get_type_name(), \"Unable to get ${tbname}_config\")\n";
4356
 
4357
        do {
4358
            print FH "\n";
4359
            print FH "  regmodel = ${top_reg_block_type}::type_id::create(\"regmodel\");\n";
4360
            print FH "  regmodel.build();\n";
4361
        } if $regmodel;
4362
 
4363
        foreach my $agent (@agent_list) {
4364
            for ( my $i = 0 ; $i < $number_of_instances{$agent} ; $i++ ) {
4365
                my $suffix = calc_suffix($i, $number_of_instances{$agent});
4366
 
4367
                align("\n", "", "");
4368
                if ( defined $nested_config_objects && $nested_config_objects eq "YES" ) {
4369
                    align("  m_${agent}${suffix}_config ", "= m_config.m_${agent}${suffix}_config;", "");
4370
                }
4371
                else {
4372
                    align("  m_${agent}${suffix}_config ", "= new(\"m_${agent}${suffix}_config\");", "");
4373
                    align("  m_${agent}${suffix}_config.vif ", "= m_config.${agent}${suffix}_vif;", "");
4374
                    align("  m_${agent}${suffix}_config.is_active ", "= m_config.is_active_${agent}${suffix};", "");
4375
                }
4376
                if ( exists $reg_access_mode{$agent} ) {
4377
 
4378
                    my $value;
4379
                    if ( ${reg_access_instance{$agent}} ne "" ) {
4380
                        $value = "regmodel${reg_access_instance{$agent}}${suffix}";
4381
                    }
4382
                    else {
4383
                        $value = "regmodel";
4384
                    }
4385
                    align("  m_${agent}${suffix}_config.regmodel ", "= ${value};", "");
4386
                }
4387
 
4388
                unless ( defined $nested_config_objects && $nested_config_objects eq "YES" ) {
4389
                    align("  m_${agent}${suffix}_config.checks_enable ", "= m_config.checks_enable_${agent}${suffix};", "");
4390
                    align("  m_${agent}${suffix}_config.coverage_enable ", "= m_config.coverage_enable_${agent}${suffix};", "");
4391
                }
4392
                gen_aligned();
4393
            }
4394
 
4395
            print FH "\n";
4396
            insert_inc_file("  ", $agent_copy_config_vars{$agent}, $agent_copy_config_vars_inline{$agent}, "agent_copy_config_vars", $tpl_fname{$agent});
4397
 
4398
            for ( my $i = 0 ; $i < $number_of_instances{$agent} ; $i++ ) {
4399
                my $suffix = calc_suffix($i, $number_of_instances{$agent});
4400
 
4401
                if ( grep( /$agent/, @stand_alone_agents ) ) {
4402
                    # agent_has_env = no                                                                                                                                           
4403
                    if ( grep( /$agent/, @top_env_agents ) ) {
4404
                        # Agent instantiated at top level. Need to set config for agent                                                                                            
4405
                        align("  uvm_config_db #(${agent}_config)::set(this, \"m_${agent}${suffix}_agent\", \"config\", m_${agent}${suffix}_config);\n", "", "");
4406
                        align("  if (m_${agent}${suffix}_config.is_active == UVM_ACTIVE )\n", "", "");
4407
                        align("    uvm_config_db #(${agent}_config)::set(this, \"m_${agent}${suffix}_agent.m_sequencer\", \"config\", m_${agent}${suffix}_config);\n", "", "");
4408
                        align("  uvm_config_db #(${agent}_config)::set(this, \"m_${agent}${suffix}_coverage\", \"config\", m_${agent}${suffix}_config);\n", "", "");
4409
                    }
4410
                    else {
4411
                        # additional_agent. Need to set config for env that contains agent                                                                                         
4412
                        align("  uvm_config_db #(${agent}_config)::set(this, \"m_$agent_parent{$agent}_env\", \"config\", m_${agent}_config);\n", "", "");
4413
                    }
4414
                }
4415
                else {
4416
                    # agent_has_env = yes. Add config to agent's own env                                                                                                           
4417
                    align("  uvm_config_db #(${agent}_config)::set(this, \"m_${agent}_env\", \"config${suffix}\", m_${agent}${suffix}_config);\n", "", "");
4418
                }
4419
 
4420
                gen_aligned();
4421
            }
4422
        }
4423
 
4424
        if ( keys %ref_model ) {
4425
            print FH "\n";
4426
            print FH "  // Default factory overrides for Syosil scoreboard\n";
4427
            print FH "  cl_syoscb_queue::type_id::set_type_override(cl_syoscb_queue_std::type_id::get());\n";
4428
        }
4429
 
4430
        foreach my $ref_model_name ( keys %ref_model ) {
4431
            print FH "\n";
4432
            print FH "  begin\n";
4433
            print FH "    bit ok;\n";
4434
            print FH "    uvm_factory factory = uvm_factory::get();\n";
4435
            print FH "\n";
4436
 
4437
            unless (exists $ref_model_compare_method{$ref_model_name}) {
4438
                $ref_model_compare_method{$ref_model_name} = "iop";
4439
            }
4440
            print FH "    if (factory.find_override_by_type(cl_syoscb_compare_base::type_id::get(), \"*\") == cl_syoscb_compare_base::type_id::get())\n";
4441
            print FH "      cl_syoscb_compare_base::type_id::set_inst_override(cl_syoscb_compare_${ref_model_compare_method{$ref_model_name}}::type_id::get(), \"m_${ref_model_name}_scoreboard.*\", this);\n";
4442
            print FH "\n";
4443
            print FH "    // Configuration object for Syosil scoreboard\n";
4444
            print FH "    m_${ref_model_name}_config = cl_syoscb_cfg::type_id::create(\"m_${ref_model_name}_config\");\n";
4445
            print FH "    m_${ref_model_name}_config.set_queues( {\"DUT\", \"REF\"} );\n";
4446
            print FH "    ok = m_${ref_model_name}_config.set_primary_queue(\"DUT\");\n";
4447
            print FH "    assert(ok);\n";
4448
 
4449
            #foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) {
4450
            #    print FH "    ok = m_${ref_model_name}_config.set_producer(\"$input\", {\"DUT\"} );\n";
4451
            #    print FH "    assert(ok);\n";
4452
            #}
4453
            foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) {
4454
                print FH "    ok = m_${ref_model_name}_config.set_producer(\"$output\", {\"DUT\", \"REF\"} );\n";
4455
                print FH "    assert(ok);\n";
4456
            }
4457
            print FH "\n";
4458
            print FH "    uvm_config_db#(cl_syoscb_cfg)::set(this, \"m_${ref_model_name}_scoreboard\", \"cfg\", m_${ref_model_name}_config);\n";
4459
            print FH "\n";
4460
            print FH "    // Instantiate reference model and Syosil scoreboard\n";
4461
            align("    m_${ref_model_name} ", "= ${ref_model_name}", "::type_id::create(\"m_${ref_model_name}\", this);");
4462
 
4463
            #foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) {
4464
            #    print FH "    m_converter_${input} = converter_${input}_t::type_id::create(\"m_converter_${input}\", this);\n";
4465
            #}
4466
            foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) {
4467
                my $name = $output;
4468
                $name =~ s/\./__/g;
4469
                align("    m_converter_${name} ", "= converter_${name}_t", "::type_id::create(\"m_converter_${name}\", this);");
4470
            }
4471
            align("    m_${ref_model_name}_scoreboard ", "= cl_syoscb", "::type_id::create(\"m_${ref_model_name}_scoreboard\", this);");
4472
            gen_aligned();
4473
            print FH "  end\n";
4474
        }
4475
 
4476
        print FH "\n";
4477
        foreach my $agent (@agent_list) {
4478
            align("  m_${agent}_env ", "= ${agent}_env", "::type_id::create(\"m_${agent}_env\", this);") if !grep( /$agent/, @stand_alone_agents );
4479
        }
4480
 
4481
        foreach my $aname (@top_env_agents) {
4482
 
4483
            for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) {
4484
                my $suffix = calc_suffix($i, $number_of_instances{$aname});
4485
 
4486
                align("\n", "", "");
4487
                align("  m_${aname}${suffix}_agent ",    "= ${aname}_agent   ", "::type_id::create(\"m_${aname}${suffix}_agent\", this);");
4488
                align("  m_${aname}${suffix}_coverage ", "= ${aname}_coverage", "::type_id::create(\"m_${aname}${suffix}_coverage\", this);");
4489
            }
4490
        }
4491
        align("\n", "", "");
4492
        gen_aligned();
4493
 
4494
        insert_inc_file("  ", $top_env_append_to_build_phase, $top_env_append_to_build_phase_inline, "top_env_append_to_build_phase", $common_tpl_fname);
4495
 
4496
        print FH "endfunction : build_phase\n";
4497
        print FH "\n";
4498
        print FH "\n";
4499
 
4500
        print FH "function void ${tbname}_env::connect_phase(uvm_phase phase);\n";
4501
        print FH "  `uvm_info(get_type_name(), \"In connect_phase\", UVM_HIGH)\n";
4502
 
4503
        foreach my $env (@env_list) {
4504
            print FH "  `uvm_info(get_type_name(), \$sformatf(\"m_${env}: %p\\n\",m_${env}), UVM_HIGH)\n";
4505
        }
4506
        print FH "\n";
4507
 
4508
        foreach my $aname (@top_env_agents) {
4509
 
4510
            for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) {
4511
                my $suffix = calc_suffix($i, $number_of_instances{$aname});
4512
 
4513
                print FH "  m_${aname}${suffix}_agent.analysis_port.connect(m_${aname}${suffix}_coverage.analysis_export);\n";
4514
                print FH "\n";
4515
            }
4516
        }
4517
 
4518
        if ( $regmodel ) {
4519
            print FH "  // Connect the register model in each agent's env\n";
4520
            foreach my $agent ( keys(%reg_access_mode) ) {
4521
 
4522
                for ( my $i = 0 ; $i < $number_of_instances{$agent} ; $i++ ) {
4523
                    my $suffix = calc_suffix($i, $number_of_instances{$agent});
4524
 
4525
                    print FH "  m_${agent}_env.m_${agent}2reg_predictor${suffix}.map     = regmodel.${reg_access_map{$agent}}${suffix};\n";
4526
                    print FH "  m_${agent}_env.m_${agent}2reg_predictor${suffix}.adapter = m_${agent}_env.m_reg2${agent}${suffix};\n";
4527
                    print FH "  regmodel.${reg_access_map{$agent}}${suffix}.set_sequencer(m_${agent}_env.m_${agent}${suffix}_agent.m_sequencer, ",
4528
                      "m_${agent}_env.m_reg2${agent}${suffix});\n";
4529
                    print FH "  regmodel.${reg_access_map{$agent}}${suffix}.set_auto_predict(0);\n";
4530
 
4531
                    print FH "\n";
4532
                }
4533
            }
4534
        }
4535
 
4536
        foreach my $ref_model_name ( keys(%ref_model) ) {
4537
            print FH "  begin\n";
4538
            print FH "    // Connect reference model and Syosil scoreboard\n";
4539
            print FH "    cl_syoscb_subscriber subscriber;\n";
4540
            print FH "\n";
4541
 
4542
            my $i = 0;
4543
            foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) {
4544
                print FH "    ${input}.analysis_port.connect(m_${ref_model_name}.analysis_export_$i);\n";
4545
 
4546
                #print FH "    subscriber = m_${ref_model_name}_scoreboard.get_subscriber(\"DUT\", \"${input}\");\n";
4547
                #print FH "    ${input}.analysis_port.connect(m_converter_${input}.analysis_export);\n";
4548
                #print FH "    m_converter_${input}.analysis_port.connect(subscriber.analysis_export);\n";
4549
                $i++;
4550
            }
4551
            $i = 0;
4552
            foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) {
4553
                print FH "\n";
4554
                print FH "    subscriber = m_${ref_model_name}_scoreboard.get_subscriber(\"REF\", \"${output}\");\n";
4555
                print FH "    m_${ref_model_name}.analysis_port_$i.connect(subscriber.analysis_export);\n";
4556
                print FH "\n";
4557
                print FH "    subscriber = m_${ref_model_name}_scoreboard.get_subscriber(\"DUT\", \"${output}\");\n";
4558
                my $name = $output;
4559
                $name =~ s/\./__/g;
4560
                print FH "    ${output}.analysis_port.connect(m_converter_${name}.analysis_export);\n";
4561
                print FH "    m_converter_${name}.analysis_port.connect(subscriber.analysis_export);\n";
4562
                $i++;
4563
            }
4564
            print FH "  end\n";
4565
        }
4566
 
4567
        print FH "\n";
4568
 
4569
        insert_inc_file("  ", $top_env_append_to_connect_phase, $top_env_append_to_connect_phase_inline, "top_env_append_to_connect_phase", $common_tpl_fname);
4570
 
4571
        print FH "endfunction : connect_phase\n";
4572
        print FH "\n";
4573
        print FH "\n";
4574
 
4575
        unless ( defined $top_env_generate_end_of_elaboration && $top_env_generate_end_of_elaboration eq "NO" )
4576
        {
4577
            unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
4578
                print FH "// You can remove end_of_elaboration_phase by setting top_env_generate_end_of_elaboration = no in file ${common_tpl_fname}\n\n";
4579
            }
4580
            print FH "function void ${tbname}_env::end_of_elaboration_phase(uvm_phase phase);\n";
4581
            print FH "  uvm_factory factory = uvm_factory::get();\n";
4582
            print FH "  `uvm_info(get_type_name(), \"Information printed from ${tbname}_env::end_of_elaboration_phase method\", UVM_MEDIUM)\n";
4583
            print FH "  `uvm_info(get_type_name(), \$sformatf(\"Verbosity threshold is %d\", get_report_verbosity_level()), UVM_MEDIUM)\n";
4584
            print FH "  uvm_top.print_topology();\n";
4585
            print FH "  factory.print();\n";
4586
            print FH "endfunction : end_of_elaboration_phase\n";
4587
            print FH "\n";
4588
            print FH "\n";
4589
        }
4590
        unless ( defined $top_env_generate_run_phase && $top_env_generate_run_phase eq "NO" )
4591
        {
4592
            unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
4593
                print FH "// You can remove run_phase by setting top_env_generate_run_phase = no in file ${common_tpl_fname}\n\n";
4594
            }
4595
            print FH "task ${tbname}_env::run_phase(uvm_phase phase);\n";
4596
            print FH "  ${tbname}_default_seq vseq;\n";
4597
            print FH "  vseq = ${tbname}_default_seq::type_id::create(\"vseq\");\n";
4598
            print FH "  vseq.set_item_context(null, null);\n";
4599
            print FH "  if ( !vseq.randomize() )\n";
4600
            print FH "    `uvm_fatal\(get_type_name(), \"Failed to randomize virtual sequence\")\n";
4601
 
4602
            foreach my $agent (@agent_list) {
4603
                if ( not (grep( /$agent/, @stand_alone_agents ) or ( $agent eq "" ) ) ) {
4604
                    align("  vseq.m_${agent}_env ", "= m_${agent}_env;", "");
4605
                }
4606
            }
4607
            foreach my $aname (@top_env_agents) {
4608
 
4609
                for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) {
4610
                    my $suffix = calc_suffix($i, $number_of_instances{$aname});
4611
 
4612
                    align("  vseq.m_${aname}${suffix}_agent ", "= m_${aname}${suffix}_agent;", "");
4613
                }
4614
            }
4615
 
4616
            if ( $regmodel ) {
4617
                align("  vseq.regmodel ", "= regmodel;", "");
4618
            }
4619
            align("  vseq.m_config ", "= m_config;", "");
4620
 
4621
            gen_aligned();
4622
 
4623
            print FH "  vseq.set_starting_phase(phase);\n";
4624
            print FH "  vseq.start(null);\n";
4625
            print FH "\n";
4626
 
4627
            insert_inc_file("  ", $top_env_append_to_run_phase, $top_env_append_to_run_phase_inline, "top_env_append_to_run_phase", $common_tpl_fname);
4628
 
4629
            print FH "endtask : run_phase\n";
4630
            print FH "\n";
4631
            print FH "\n";
4632
        }
4633
    }
4634
 
4635
    insert_inc_file("", $top_env_inc_after_class, $top_env_inc_after_inline, "top_env_inc_after_class", $common_tpl_fname);
4636
 
4637
    print FH "`endif // " . uc($tbname) . "_ENV_SV\n";
4638
    print FH "\n";
4639
    close(FH);
4640
}
4641
 
4642
 
4643
sub gen_port_converter {
4644
 
4645
    # Port converter class is only necessary if there is a reference model
4646
    unless ( keys %ref_model ) {
4647
        return;
4648
    }
4649
 
4650
    $dir = $project . "/tb/" . $tbname;
4651
    open( FH, ">" . $dir . "/sv/port_converter.sv" )
4652
      || die "Exiting due to Error: can't open env: $tbname";
4653
 
4654
    write_file_header "port_converter.sv", "Analysis port type converter class for use with Syosil scoreboard";
4655
 
4656
    unless ( defined $syosil_scoreboard_src_path ) {
4657
        warning_prompt("ref_model specified in $common_tpl_fname but \$syosil_scoreboard_src_path has not been defined");
4658
    }
4659
 
4660
    print FH "`ifndef PORT_CONVERTER_SV\n";
4661
    print FH "`define PORT_CONVERTER_SV\n";
4662
    print FH "\n";
4663
 
4664
    print FH "\n";
4665
    print FH "class port_converter #(type T = uvm_sequence_item) extends uvm_subscriber #(T);\n";
4666
    print FH "  `uvm_component_param_utils(port_converter#(T))\n";
4667
    print FH "\n";
4668
    print FH "  // For connecting analysis port of monitor to analysis export of Syosil scoreboard\n";
4669
    print FH "\n";
4670
    print FH "  uvm_analysis_port #(uvm_sequence_item) analysis_port;\n";
4671
    print FH "\n";
4672
    print FH "  function new(string name, uvm_component parent);\n";
4673
    print FH "    super.new(name, parent);\n";
4674
    print FH "    analysis_port = new(\"a_port\", this);\n";
4675
    print FH "  endfunction\n";
4676
    print FH "\n";
4677
    print FH "  function void write(T t);\n";
4678
    print FH "    analysis_port.write(t);\n";
4679
    print FH "  endfunction\n";
4680
    print FH "\n";
4681
    print FH "endclass\n";
4682
    print FH "\n";
4683
    print FH "\n";
4684
 
4685
    print FH "`endif // PORT_CONVERTER_SV\n";
4686
    print FH "\n";
4687
    close(FH);
4688
}
4689
 
4690
 
4691
sub gen_ref_model {
4692
    my ($ref_model_name) = @_;
4693
 
4694
    $dir = $project . "/tb/" . $tbname;
4695
    open( FH, ">" . $dir . "/sv/$ref_model_name.sv" )
4696
      || die "Exiting due to Error: can't open env: $tbname";
4697
 
4698
    write_file_header "$ref_model_name.sv", "Reference model for use with Syosil scoreboard";
4699
 
4700
    unless ( defined $syosil_scoreboard_src_path ) {
4701
        warning_prompt("ref_model specified in $common_tpl_fname but \$syosil_scoreboard_src_path has not been defined");
4702
    }
4703
 
4704
    print FH "`ifndef " . uc($ref_model_name) . "_SV\n";
4705
    print FH "`define " . uc($ref_model_name) . "_SV\n";
4706
    print FH "\n";
4707
 
4708
    insert_inc_file("", $ref_model_inc_before_class{$ref_model_name}, $ref_model_inc_before_inline{$ref_model_name}, "ref_model_inc_before_class", $common_tpl_fname);
4709
 
4710
    print FH "\n";
4711
 
4712
    my $i = 0;
4713
    foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) {
4714
        print FH "`uvm_analysis_imp_decl(_${ref_model_name}_$i)\n";
4715
        $i++;
4716
    }
4717
 
4718
    print FH "\n";
4719
    print FH "class $ref_model_name extends uvm_component;\n";
4720
    print FH "  `uvm_component_utils($ref_model_name)\n";
4721
    print FH "\n";
4722
    $i = 0;
4723
    foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) {
4724
        unless (exists ${agent_type_by_inst{$input}}) {
4725
            warning_prompt("ref_model_input $input specified in $common_tpl_fname cannot be found as the instance name of an agent in the generated code");
4726
        }
4727
        $agent_name = ${agent_type_by_inst{$input}};
4728
        print FH "  uvm_analysis_imp_${ref_model_name}_$i #($agent_item_types{$agent_name}, $ref_model_name) analysis_export_$i; // $input\n";
4729
        $i++;
4730
    }
4731
    print FH "\n";
4732
    $i = 0;
4733
    foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) {
4734
        $agent_name = ${agent_type_by_inst{$output}};
4735
        if ($agent_name eq "") {
4736
            warning_prompt("ref_model_input $output specified in $common_tpl_fname cannot be found as the instance name of an agent in the generated code");
4737
        }
4738
        print FH "  uvm_analysis_port #(uvm_sequence_item) analysis_port_$i; // $output\n";
4739
        $i++;
4740
    }
4741
    print FH "\n";
4742
    print FH "  extern function new(string name, uvm_component parent);\n";
4743
 
4744
    $i = 0;
4745
    foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) {
4746
        $agent_name = ${agent_type_by_inst{$input}};
4747
 
4748
        print FH "  extern function void write_${ref_model_name}_$i(input " . $agent_item_types{$agent_name} . " t);\n";
4749
        $i++;
4750
    }
4751
 
4752
    print FH "\n";
4753
 
4754
    insert_inc_file("  ", $ref_model_inc_inside_class{$ref_model_name}, $ref_model_inc_inside_inline{$ref_model_name}, "ref_model_inc_inside_class", $common_tpl_fname);
4755
 
4756
    print FH "endclass\n";
4757
    print FH "\n";
4758
    print FH "\n";
4759
    print FH "function ${ref_model_name}::new(string name, uvm_component parent);\n";
4760
    print FH "  super.new(name, parent);\n";
4761
    $i = 0;
4762
    foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) {
4763
        print FH "  analysis_export_$i = new(\"analysis_export_$i\", this);\n";
4764
        $i++;
4765
    }
4766
    $i = 0;
4767
    foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) {
4768
        print FH "  analysis_port_$i   = new(\"analysis_port_$i\",   this);\n";
4769
        $i++;
4770
    }
4771
    print FH "endfunction : new\n";
4772
    print FH "\n";
4773
    print FH "\n";
4774
 
4775
    insert_inc_file("", $ref_model_inc_after_class{$ref_model_name}, $ref_model_inc_after_inline{$ref_model_name}, "ref_model_inc_after_class", $common_tpl_fname);
4776
 
4777
    print FH "`endif // " . uc($ref_model_name) . "_SV\n";
4778
    print FH "\n";
4779
}
4780
 
4781
 
4782
sub gen_top_config {
4783
    $dir = $project . "/tb/" . $tbname;
4784
    open( FH, ">" . $dir . "/sv/" . $tbname . "_config.sv" )
4785
      || die "Exiting due to Error: can't open config: $tbname";
4786
 
4787
    write_file_header "${tbname}_config.sv", "Configuration for $tbname";
4788
 
4789
    print FH "`ifndef " . uc($tbname) . "_CONFIG_SV\n";
4790
    print FH "`define " . uc($tbname) . "_CONFIG_SV\n";
4791
    print FH "\n";
4792
 
4793
    insert_inc_file("", $top_env_config_inc_before_class, $top_env_config_inc_before_inline, "top_env_config_inc_before_class", $common_tpl_fname);
4794
 
4795
    print FH "class ${tbname}_config extends uvm_object;\n";
4796
    print FH "\n";
4797
    print FH "  // Do not register config class with the factory\n";
4798
    print FH "\n";
4799
 
4800
    if ( defined $nested_config_objects && $nested_config_objects eq "YES" )
4801
    {
4802
        for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) {
4803
            my $agent = $agent_list[$i];
4804
 
4805
            for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) {
4806
                my $suffix = calc_suffix($j, $number_of_instances{$agent});
4807
 
4808
                align("  rand ${agent}_config  ", "m_${agent}${suffix}_config;", "");
4809
            }
4810
        }
4811
    }
4812
    else
4813
    {
4814
        for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) {
4815
            my $agent = $agent_list[$i];
4816
 
4817
            for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) {
4818
                my $suffix = calc_suffix($j, $number_of_instances{$agent});
4819
 
4820
                align("  virtual ${all_agent_ifs[$i]}  ", "${agent}${suffix}_vif;", "");
4821
            }
4822
        }
4823
        align("\n", "", "");
4824
 
4825
        for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) {
4826
            my $agent = $agent_list[$i];
4827
 
4828
            for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) {
4829
                my $suffix = calc_suffix($j, $number_of_instances{$agent});
4830
 
4831
                align("  uvm_active_passive_enum  ", "is_active_${agent}${suffix} ", "= UVM_ACTIVE;");
4832
            }
4833
        }
4834
        align("\n", "", "") if ( @all_agent_ifs > 1);
4835
 
4836
        for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) {
4837
            my $agent = $agent_list[$i];
4838
 
4839
            for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) {
4840
                my $suffix = calc_suffix($j, $number_of_instances{$agent});
4841
 
4842
                align("  bit  ", "checks_enable_${agent}${suffix};", "");
4843
            }
4844
        }
4845
        align("\n", "", "") if ( @all_agent_ifs > 1);
4846
 
4847
 
4848
        for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) {
4849
            my $agent = $agent_list[$i];
4850
 
4851
            for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) {
4852
                my $suffix = calc_suffix($j, $number_of_instances{$agent});
4853
 
4854
                align("  bit  ", "coverage_enable_${agent}${suffix};", "");
4855
            }
4856
        }
4857
    }
4858
 
4859
    gen_aligned();
4860
 
4861
    print FH "\n";
4862
 
4863
    unless ( @common_config_var_array ) {
4864
        print FH "  // You can insert variables here by setting config_var in file ${common_tpl_fname}\n";
4865
    }
4866
    foreach my $var_decl (@common_config_var_array) {
4867
        print FH "  $var_decl\n";
4868
    }
4869
    print FH "\n";
4870
 
4871
    unless ( defined $top_env_config_generate_methods_inside_class && $top_env_config_generate_methods_inside_class eq "NO" )
4872
    {
4873
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
4874
            print FH "  // You can remove new by setting top_env_config_generate_methods_inside_class = no in file ${common_tpl_fname}\n\n";
4875
        }
4876
        print FH "  extern function new(string name = \"\");\n";
4877
        print FH "\n";
4878
    }
4879
 
4880
    insert_inc_file("  ", $top_env_config_inc_inside_class, $top_env_config_inc_inside_inline, "top_env_config_inc_inside_class", $common_tpl_fname);
4881
 
4882
    print FH "endclass : " . $tbname . "_config \n";
4883
    print FH "\n";
4884
    print FH "\n";
4885
 
4886
    unless ( defined $top_env_config_generate_methods_after_class && $top_env_config_generate_methods_after_class eq "NO" )
4887
    {
4888
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
4889
            print FH "// You can remove new by setting top_env_config_generate_methods_after_class = no in file ${common_tpl_fname}\n\n";
4890
        }
4891
        print FH "function ${tbname}_config::new(string name = \"\");\n";
4892
        print FH "  super.new(name);\n";
4893
        print FH "\n";
4894
 
4895
        if ( defined $nested_config_objects && $nested_config_objects eq "YES" )
4896
        {
4897
            for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) {
4898
                my $agent = $agent_list[$i];
4899
 
4900
                for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) {
4901
                    my $suffix = calc_suffix($j, $number_of_instances{$agent});
4902
 
4903
                    align("  m_${agent}${suffix}_config ", "= new(\"m_${agent}${suffix}_config\");", "");
4904
 
4905
                    my $value;
4906
                    if ( exists $agent_is_active{$agent} ) {
4907
                        $value = "$agent_is_active{$agent}";
4908
                    }
4909
                    else {
4910
                        $value = "UVM_ACTIVE";
4911
                    }
4912
                    align("  m_${agent}${suffix}_config.is_active ", "= $value;", "");
4913
 
4914
                    if ( exists $agent_checks_enable{$agent} and $agent_checks_enable{$agent} eq "NO" ) {
4915
                        $value = "0";
4916
                    }
4917
                    else {
4918
                        $value = "1";
4919
                    }
4920
                    align("  m_${agent}${suffix}_config.checks_enable ", "= $value;", "");
4921
 
4922
                    if ( exists $agent_coverage_enable{$agent} and $agent_coverage_enable{$agent} eq "NO" ) {
4923
                        $value = "0";
4924
                    }
4925
                    else {
4926
                        $value = "1";
4927
                    }
4928
                    align("  m_${agent}${suffix}_config.coverage_enable ", "= $value;", "");
4929
                    align("\n", "", "");
4930
                }
4931
            }
4932
            gen_aligned();
4933
        }
4934
        insert_inc_file("  ", $top_env_config_append_to_new, $top_env_config_append_to_new_inline, "top_env_config_append_to_new", $common_tpl_fname);
4935
 
4936
        print FH "endfunction : new\n";
4937
        print FH "\n";
4938
        print FH "\n";
4939
    }
4940
 
4941
    insert_inc_file("", $top_env_config_inc_after_class, $top_env_config_inc_after_inline, "top_env_config_inc_after_class", $common_tpl_fname);
4942
 
4943
    print FH "`endif // " . uc($tbname) . "_CONFIG_SV\n";
4944
    print FH "\n";
4945
    close(FH);
4946
}
4947
 
4948
sub gen_top_seq_lib {
4949
    $dir = $project . "/tb/" . $tbname;
4950
    open( FH, ">" . $dir . "/sv/" . $tbname . "_seq_lib.sv" )
4951
      || die "Exiting due to Error: can't open seq_lib: $tbname";
4952
 
4953
    write_file_header "${tbname}_seq_lib.sv", "Sequence for $tbname";
4954
 
4955
    print FH "`ifndef " . uc($tbname) . "_SEQ_LIB_SV\n";
4956
    print FH "`define " . uc($tbname) . "_SEQ_LIB_SV\n";
4957
    print FH "\n";
4958
 
4959
    print FH "class ${tbname}_default_seq extends uvm_sequence #(uvm_sequence_item);\n";
4960
    print FH "\n";
4961
    print FH "  `uvm_object_utils(" . $tbname . "_default_seq)\n";
4962
    print FH "\n";
4963
 
4964
    if ( $regmodel ) {
4965
        align("  $top_reg_block_type ", "regmodel;", "");
4966
    }
4967
    align("  ${tbname}_config ", "m_config;\n", "");
4968
 
4969
    foreach my $agent (@agent_list) {
4970
        do {
4971
            align("  ${agent}_env  ", "m_${agent}_env;", "");
4972
        } unless grep( /$agent/, @stand_alone_agents );
4973
    }
4974
 
4975
    foreach my $aname (@top_env_agents) {
4976
 
4977
        for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) {
4978
            my $suffix = calc_suffix($i, $number_of_instances{$aname});
4979
 
4980
            align("  ${aname}_agent  ", "m_${aname}${suffix}_agent;", "");
4981
        }
4982
    }
4983
 
4984
    foreach my $env (@env_list) {
4985
        $env =~ /(\w+)_env/;
4986
        if ( exists $reg_access_mode{$1} ) {
4987
            push @reg_env, $1;
4988
            align("  ${env}_default_seq  ", "m_${env}_seq;", "");
4989
        }
4990
        else {    #env that does not access regmodel
4991
            push @non_reg_env, $1;
4992
            align("  ${1}_env_default_seq  ", "m_${1}_env_seq;", "");
4993
        }
4994
    }
4995
 
4996
    gen_aligned();
4997
 
4998
    print FH "\n";
4999
    print FH "  // Number of times to repeat child sequences\n";
5000
 
5001
    if ( defined $top_default_seq_count ) {
5002
        print FH "  int m_seq_count = $top_default_seq_count;\n";
5003
    }
5004
    else {
5005
        print FH "  int m_seq_count = 1;\n";
5006
    }
5007
    print FH "\n";
5008
 
5009
    do {
5010
        print FH "\n";
5011
        print FH "  // Example built-in register sequences\n";
5012
        print FH "  //uvm_reg_hw_reset_seq  m_reset_seq;\n";
5013
        print FH "  //uvm_reg_bit_bash_seq  m_bit_bash_seq;\n";
5014
        print FH "\n";
5015
    } if $regmodel;
5016
    print FH "  extern function new(string name = \"\");\n";
5017
    print FH "  extern task body();\n";
5018
    print FH "  extern task pre_start();\n";
5019
    print FH "  extern task post_start();\n";
5020
    print FH "\n";
5021
    print FH "`ifndef UVM_POST_VERSION_1_1\n";
5022
    print FH "  // Functions to support UVM 1.2 objection API in UVM 1.1\n";
5023
    print FH "  extern function uvm_phase get_starting_phase();\n";
5024
    print FH "  extern function void set_starting_phase(uvm_phase phase);\n";
5025
    print FH "`endif\n";
5026
    print FH "\n";
5027
    print FH "endclass : " . $tbname . "_default_seq\n";
5028
    print FH "\n";
5029
    print FH "\n";
5030
    print FH "function ${tbname}_default_seq::new(string name = \"\");\n";
5031
    print FH "  super.new(name);\n";
5032
    print FH "endfunction : new\n";
5033
    print FH "\n";
5034
    print FH "\n";
5035
    print FH "task ${tbname}_default_seq::body();\n";
5036
    print FH "  `uvm_info(get_type_name(), \"Default sequence starting\", UVM_HIGH)\n";
5037
    print FH "\n";
5038
 
5039
    foreach my $env (@reg_env, @non_reg_env) {
5040
        align("  m_${env}_env_seq ", "= ${env}_env_default_seq", "::type_id::create(\"m_${env}_env_seq\");");
5041
 
5042
        # For the purposes of random stability, although the virtual sequence is actually running on the null sequencer,
5043
        # pretend instead that it is running on the sequencer of the agent.
5044
        # If there are multiple instances of the agent, pick the first
5045
 
5046
        my $suffix = calc_suffix(0, $number_of_instances{$env});
5047
        my $sequencer_instance_name = "m_${env}_env.m_${env}${suffix}_agent.m_sequencer";
5048
 
5049
        align("  m_${env}_env_seq.set_item_context(this, ${sequencer_instance_name});\n", "", "");
5050
        align("  m_${env}_env_seq.set_starting_phase( get_starting_phase() );\n", "", "");
5051
 
5052
        if ( grep( /$env/, @reg_env ) ) {
5053
            $aname = $env;
5054
            for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) {
5055
                my $suffix = calc_suffix($i, $number_of_instances{$aname});
5056
 
5057
                if ( ${reg_access_instance{$aname}} ne "" ) {
5058
                    align("  m_${env}_env_seq.regmodel${suffix} ", "= regmodel${reg_access_instance{$aname}}${suffix};", "");
5059
                }
5060
                else {
5061
                    # If instance = "", use the top-level regmodel
5062
                    align("  m_${env}_env_seq.regmodel${suffix} ", "= regmodel;", "");
5063
                }
5064
                align("  m_${env}_env_seq.m_config${suffix} ", "= m_${aname}_env.m_${aname}${suffix}_agent.m_config;", "");
5065
            }
5066
        }
5067
        align("\n", "", "");
5068
    }
5069
 
5070
    gen_aligned();
5071
 
5072
    print FH "\n";
5073
    print FH "  repeat (m_seq_count)\n";
5074
    print FH "  begin\n";
5075
 
5076
    my @vseq_list;
5077
    if ($regmodel) {
5078
        foreach my $env (@reg_env) {
5079
            print FH "    if ( !m_${env}_env_seq.randomize() )\n";
5080
            print FH "      `uvm_error(get_type_name(), \"Failed to randomize sequence\")\n";
5081
            push @vseq_list, "m_${env}_env_seq";
5082
        }
5083
    }
5084
    foreach my $env (@non_reg_env) {
5085
        push @vseq_list, "m_${env}_env_seq";
5086
        print FH "    if ( !m_${env}_env_seq.randomize() )\n";
5087
        print FH "      `uvm_error(get_type_name(), \"Failed to randomize sequence\")\n";
5088
        print FH "    m_${env}_env_seq.m_env = m_${env}_env;\n";
5089
    }
5090
 
5091
    print FH "    fork\n";
5092
    foreach my $vseq (@vseq_list) {
5093
        print FH "      ${vseq}.start(null, this);\n";
5094
    }
5095
    foreach my $aname (@top_env_agents) {
5096
 
5097
        for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) {
5098
            my $suffix = calc_suffix($i, $number_of_instances{$aname});
5099
            my $sequencer_instance_name = "m_${aname}${suffix}_agent.m_sequencer";
5100
 
5101
            print FH "      if (m_${aname}${suffix}_agent.m_config.is_active == UVM_ACTIVE)\n";
5102
            print FH "      begin\n";
5103
            print FH "        ${aname}_default_seq seq;\n";
5104
            print FH "        seq = ${aname}_default_seq::type_id::create(\"seq\");\n";
5105
            print FH "        seq.set_item_context(this, ${sequencer_instance_name});\n";
5106
            print FH "        if ( !seq.randomize() )\n";
5107
            print FH "          `uvm_error(get_type_name(), \"Failed to randomize sequence\")\n";
5108
            print FH "        seq.m_config = m_${aname}${suffix}_agent.m_config;\n";
5109
            print FH "        seq.set_starting_phase( get_starting_phase() );\n";
5110
            print FH "        seq.start(${sequencer_instance_name}, this);\n";
5111
            print FH "      end\n";
5112
 
5113
        }
5114
    }
5115
    print FH "    join\n";
5116
    print FH "  end\n";
5117
    print FH "\n";
5118
    print FH "  `uvm_info(get_type_name(), \"Default sequence completed\", UVM_HIGH)\n";
5119
    print FH "endtask : body\n";
5120
    print FH "\n";
5121
    print FH "\n";
5122
 
5123
    print FH "task ${tbname}_default_seq::pre_start();\n";
5124
    print FH "  uvm_phase phase = get_starting_phase();\n";
5125
    print FH "  if (phase != null)\n";
5126
    print FH "    phase.raise_objection(this);\n";
5127
    print FH "endtask: pre_start\n";
5128
    print FH "\n";
5129
    print FH "\n";
5130
    print FH "task ${tbname}_default_seq::post_start();\n";
5131
    print FH "  uvm_phase phase = get_starting_phase();\n";
5132
    print FH "  if (phase != null) \n";
5133
    print FH "    phase.drop_objection(this);\n";
5134
    print FH "endtask: post_start\n";
5135
    print FH "\n";
5136
    print FH "\n";
5137
    print FH "`ifndef UVM_POST_VERSION_1_1\n";
5138
    print FH "function uvm_phase ${tbname}_default_seq::get_starting_phase();\n";
5139
    print FH "  return starting_phase;\n";
5140
    print FH "endfunction: get_starting_phase\n";
5141
    print FH "\n";
5142
    print FH "\n";
5143
    print FH "function void ${tbname}_default_seq::set_starting_phase(uvm_phase phase);\n";
5144
    print FH "  starting_phase = phase;\n";
5145
    print FH "endfunction: set_starting_phase\n";
5146
    print FH "`endif\n";
5147
    print FH "\n";
5148
    print FH "\n";
5149
 
5150
    insert_inc_file("", $top_seq_inc, $top_seq_inc_inline, "top_seq_inc", $common_tpl_fname);
5151
 
5152
    print FH "`endif // " . uc($tbname) . "_SEQ_LIB_SV\n";
5153
    print FH "\n";
5154
 
5155
    close(FH);
5156
}
5157
 
5158
sub gen_top_test {
5159
    $dir = $project . "/tb/" . $tbname . "_test";
5160
    open( FH, ">" . $dir . "/sv/" . $tbname . "_test_pkg.sv" )
5161
      || die "can't open test: " . $tbname . "_test_pkg.sv";
5162
 
5163
    write_file_header "${tbname}_test_pkg.sv", "Test package for $tbname";
5164
 
5165
    print FH "`ifndef " . uc($tbname) . "_TEST_PKG_SV\n";
5166
    print FH "`define " . uc($tbname) . "_TEST_PKG_SV\n";
5167
    print FH "\n";
5168
    print FH "package " . $tbname . "_test_pkg;\n";
5169
    print FH "\n";
5170
    print FH "  `include \"uvm_macros.svh\"\n";
5171
    print FH "\n";
5172
    print FH "  import uvm_pkg::*;\n";
5173
    print FH "\n";
5174
    print FH "  import regmodel_pkg::*;\n\n" if $regmodel;
5175
 
5176
    print FH "  import ${common_pkg}::*;\n" if $common_pkg;
5177
    print FH "  import ${common_env_pkg}::*;\n" if $common_env_pkg;
5178
 
5179
    foreach my $agent (@agent_list) {
5180
        print FH "  import ${agent}_pkg::*;\n";
5181
    }
5182
    print FH "  import " . $tbname . "_pkg::*;\n";
5183
    print FH "\n";
5184
    print FH "  `include \"" . $tbname . "_test.sv\"\n";
5185
    print FH "\n";
5186
    print FH "endpackage : " . $tbname . "_test_pkg\n";
5187
    print FH "\n";
5188
    print FH "`endif // " . uc($tbname) . "_TEST_PKG_SV\n";
5189
    print FH "\n";
5190
    close(FH);
5191
 
5192
    $dir = $project . "/tb/" . $tbname . "_test";
5193
 
5194
    # define specific tests
5195
    $dir = $project . "/tb/" . $tbname . "_test";
5196
    open( FH, ">" . $dir . "/sv/" . $tbname . "_test.sv" )
5197
      || die "Exiting due to Error: can't open test: " . $tbname . "_test.sv";
5198
 
5199
    write_file_header "${tbname}_test.sv", "Test class for ${tbname} (included in package ${tbname}_test_pkg)";
5200
 
5201
    print FH "`ifndef " . uc($tbname) . "_TEST_SV\n";
5202
    print FH "`define " . uc($tbname) . "_TEST_SV\n";
5203
    print FH "\n";
5204
 
5205
    insert_inc_file("", $test_inc_before_class, $test_inc_before_inline, "test_inc_before_class", $common_tpl_fname);
5206
 
5207
    print FH "class ${tbname}_test extends uvm_test;\n";
5208
    print FH "\n";
5209
    print FH "  `uvm_component_utils(" . $tbname . "_test)\n";
5210
    print FH "\n";
5211
    print FH "  ${tbname}_env m_env;\n";
5212
    print FH "\n";
5213
    print FH "  extern function new(string name, uvm_component parent);\n";
5214
    print FH "\n";
5215
 
5216
    unless ( defined $test_generate_methods_inside_class && $test_generate_methods_inside_class eq "NO" )
5217
    {
5218
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
5219
            print FH "  // You can remove build_phase method by setting test_generate_methods_inside_class = no in file ${common_tpl_fname}\n\n";
5220
        }
5221
        print FH "  extern function void build_phase(uvm_phase phase);\n";
5222
        print FH "\n";
5223
    }
5224
 
5225
    insert_inc_file("  ", $test_inc_inside_class, $test_inc_inside_inline, "test_inc_inside_class", $common_tpl_fname);
5226
 
5227
    print FH "endclass : ${tbname}_test\n";
5228
    print FH "\n";
5229
    print FH "\n";
5230
    print FH "function ${tbname}_test::new(string name, uvm_component parent);\n";
5231
    print FH "  super.new(name, parent);\n";
5232
    print FH "endfunction : new\n";
5233
    print FH "\n";
5234
    print FH "\n";
5235
 
5236
    unless ( defined $test_generate_methods_after_class && $test_generate_methods_after_class eq "NO" )
5237
    {
5238
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
5239
            print FH "// You can remove build_phase method by setting test_generate_methods_after_class = no in file ${common_tpl_fname}\n\n";
5240
        }
5241
        print FH "function void ${tbname}_test::build_phase(uvm_phase phase);\n";
5242
        print FH "\n";
5243
 
5244
        insert_inc_file("  ", $test_prepend_to_build_phase, $test_prepend_to_build_phase_inline, "test_prepend_to_build_phase", $common_tpl_fname);
5245
 
5246
        print FH "  // You could modify any test-specific configuration object variables here\n";
5247
        print FH "\n";
5248
 
5249
        do {
5250
            print FH "  // Include reg coverage from the register model\n";
5251
            print FH "  uvm_reg::include_coverage(\"*\", UVM_CVR_ALL);\n";
5252
        } if $regmodel;
5253
 
5254
        print FH "\n";
5255
 
5256
        foreach my $factory_override ( keys %agent_factory_set ) {
5257
            if ($factory_override ne "") {
5258
                align("  ${factory_override}", "::type_id::set_type_override($agent_factory_set{$factory_override}::get_type());", "");
5259
            }
5260
        }
5261
 
5262
        foreach my $factory_override ( keys %top_factory_set ) {
5263
            if ($factory_override ne "") {
5264
                align("  ${factory_override}", "::type_id::set_type_override($top_factory_set{$factory_override}::get_type());", "");
5265
            }
5266
        }
5267
 
5268
        gen_aligned();
5269
 
5270
        print FH "\n";
5271
        print FH "  m_env = ${tbname}_env::type_id::create(\"m_env\", this);\n";
5272
        print FH "\n";
5273
 
5274
        insert_inc_file("  ", $test_append_to_build_phase, $test_append_to_build_phase_inline, "test_append_to_build_phase", $common_tpl_fname);
5275
 
5276
        print FH "endfunction : build_phase\n";
5277
        print FH "\n";
5278
        print FH "\n";
5279
    }
5280
 
5281
    insert_inc_file("", $test_inc_after_class, $test_inc_after_inline, "test_inc_after_class", $common_tpl_fname);
5282
 
5283
    print FH "`endif // " . uc($tbname) . "_TEST_SV\n";
5284
    print FH "\n";
5285
    close(FH);
5286
 
5287
}
5288
 
5289
sub gen_top() {
5290
    ### generate top modules
5291
    $dir = $project . "/tb/" . $tbname;
5292
 
5293
    ### Test Harness
5294
    open( FH, ">" . $dir . "_tb/sv/" . $tbname . "_th.sv" )
5295
      || die "Exiting due to Error: can't open include file: " . $tbname . "_th.sv";
5296
    write_file_header "${tbname}_th.sv", "Test Harness";
5297
 
5298
    if ( $split_transactors eq "YES" ) {
5299
      $th_module_name = "${tbname}_hdl_th";
5300
    }
5301
    else {
5302
      $th_module_name = "${tbname}_th";
5303
    }
5304
 
5305
    print FH "module ${th_module_name};\n";
5306
    print FH "\n";
5307
    print FH "  timeunit      $timeunit;\n";
5308
    print FH "  timeprecision $timeprecision;\n";
5309
    print FH "\n";
5310
    print FH "  import ${common_pkg}::*;\n" if $common_pkg;
5311
    print FH "  import ${common_env_pkg}::*;\n" if $common_env_pkg;
5312
    print FH "\n";
5313
 
5314
    unless ( defined $th_generate_clock_and_reset && $th_generate_clock_and_reset eq "NO" )
5315
    {
5316
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
5317
            print FH "  // You can remove clock and reset below by setting th_generate_clock_and_reset = no in file ${common_tpl_fname}\n\n";
5318
        }
5319
        print FH "  // Example clock and reset declarations\n";
5320
        print FH "  logic clock = 0;\n";
5321
        print FH "  logic reset;\n";
5322
        print FH "\n";
5323
        print FH "  // Example clock generator process\n";
5324
        print FH "  always #10 clock = ~clock;\n";
5325
        print FH "\n";
5326
 
5327
        print FH "  // Example reset generator process\n";
5328
        print FH "  initial\n";
5329
        print FH "  begin\n";
5330
        print FH "    reset = 0;         // Active low reset in this example\n";
5331
        print FH "    #75 reset = 1;\n";
5332
        print FH "  end\n";
5333
 
5334
        if (@rlist) {#
5335
            align("\n", "", "");
5336
 
5337
            for ( $i = 0 ; $i < @rlist ; $i = $i + 2 ) {
5338
                $agent_name = $rlist[$i];
5339
                unless ( exists $generate_interface_instance{$agent_name} && $generate_interface_instance{$agent_name} eq "NO" ) {
5340
 
5341
                    for ( my $j = 0 ; $j < $number_of_instances{$agent_name} ; $j++ ) {
5342
                        my $suffix = "_${j}";
5343
 
5344
                        align("  assign ${agent_name}_if${suffix}.$rlist[ $i + 1 ] ", "= reset;", "");
5345
                    }
5346
                }
5347
            }
5348
        }
5349
 
5350
        if (@clist) {
5351
            align("\n", "", "");
5352
            for ( $i = 0 ; $i < @clist ; $i = $i + 2 ) {
5353
                $agent_name = $clist[$i];
5354
                unless ( exists $generate_interface_instance{$agent_name} && $generate_interface_instance{$agent_name} eq "NO" ) {
5355
 
5356
                    for ( my $j = 0 ; $j < $number_of_instances{$agent_name} ; $j++ ) {
5357
                        my $suffix = "_${j}";
5358
 
5359
                        align("  assign ${agent_name}_if${suffix}.$clist[ $i + 1 ] ", "= clock;", "");
5360
                    }
5361
                }
5362
            }
5363
        }
5364
        gen_aligned();
5365
 
5366
        print FH "\n";
5367
    }
5368
 
5369
    insert_inc_file("  ", $th_inc_inside_module, $th_inc_inside_inline, "th_inc_inside_module", $common_tpl_fname);
5370
 
5371
    align("  // Pin-level interfaces connected to DUT\n", "", "");
5372
    unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
5373
        align("  // You can remove interface instances by setting generate_interface_instance = no in the interface template file\n\n", "", "");
5374
    }
5375
    foreach my $agent_name (@agent_list) {
5376
        unless ( exists $generate_interface_instance{$agent_name} && $generate_interface_instance{$agent_name} eq "NO" )
5377
        {
5378
            my $interface_type;
5379
            if ( exists $byo_interface{$agent_name} ) {
5380
                $interface_type = $byo_interface{$agent_name};
5381
            }
5382
            else {
5383
                $interface_type = "${agent_name}_if";
5384
            }
5385
 
5386
            for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) {
5387
                my $suffix = "_${i}";
5388
                align("  ${interface_type}  ", "${agent_name}_if${suffix} ();", "");
5389
            }
5390
        }
5391
    }
5392
    align("\n", "", "");
5393
 
5394
    if ( $split_transactors eq "YES" ) {
5395
        align("  // BFM interfaces that communicate with proxy transactors in UVM environment\n", "", "");
5396
        foreach my $agent_name (@agent_list) {
5397
            for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) {
5398
                my $suffix = "_${i}";
5399
                align("  ${agent_name}_bfm  ", "${agent_name}_bfm${suffix} (${agent_name}_if${suffix});", "");
5400
            }
5401
        }
5402
        align("\n", "", "");
5403
    }
5404
    gen_aligned();
5405
 
5406
    gen_dut_inst();
5407
 
5408
    print FH "\n";
5409
    print FH "endmodule\n";
5410
    print FH "\n";
5411
    close(FH);
5412
 
5413
    ###Testbench
5414
 
5415
    open( FH, ">" . $dir . "_tb/sv/" . $tbname . "_tb.sv" )
5416
      || die "Exiting due to Error: can't open include file: ${tbname}_tb.sv";
5417
 
5418
    write_file_header("${tbname}_tb.sv","Testbench");
5419
 
5420
    if ( $split_transactors eq "YES" ) {
5421
      $tb_module_name = "${tbname}_untimed_tb";
5422
    }
5423
    else {
5424
      $tb_module_name = "${tbname}_tb";
5425
    }
5426
 
5427
 
5428
    print FH "module ${tb_module_name};\n";
5429
    print FH "\n";
5430
    print FH "  timeunit      $timeunit;\n";
5431
    print FH "  timeprecision $timeprecision;\n";
5432
    print FH "\n";
5433
    print FH "  `include \"uvm_macros.svh\"\n";
5434
    print FH "\n";
5435
    print FH "  import uvm_pkg::*;\n";
5436
    print FH "\n";
5437
    print FH "  import ${common_pkg}::*;\n" if $common_pkg;
5438
    print FH "  import ${common_env_pkg}::*;\n" if $common_env_pkg;
5439
    print FH "  import ${tbname}_test_pkg::*;\n";
5440
    print FH "  import ${tbname}_pkg::${tbname}_config;\n";
5441
    print FH "\n";
5442
    print FH "  // Configuration object for top-level environment\n";
5443
    print FH "  ${tbname}_config top_env_config;\n";
5444
    print FH "\n";
5445
 
5446
    unless ( $dual_top eq "YES" )
5447
    {
5448
        print FH "  // Test harness\n";
5449
        print FH "  ${th_module_name} th();\n";
5450
        print FH "\n";
5451
    }
5452
 
5453
    insert_inc_file("  ", $tb_inc_inside_module, $tb_inc_inside_inline, "tb_inc_inside_module", $common_tpl_fname);
5454
 
5455
    unless ( defined $tb_generate_run_test && $tb_generate_run_test eq "NO" )
5456
    {
5457
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
5458
            print FH "  // You can remove the initial block below by setting tb_generate_run_test = no in file ${common_tpl_fname}\n\n";
5459
        }
5460
        print FH "  initial\n";
5461
        print FH "  begin\n";
5462
 
5463
        insert_inc_file("    ", $tb_prepend_to_initial, $tb_prepend_to_initial_inline, "tb_prepend_to_initial", $common_tpl_fname);
5464
 
5465
        print FH "    // Create and populate top-level configuration object\n";
5466
        print FH "    top_env_config = new(\"top_env_config\");\n";
5467
        print FH "    if ( !top_env_config.randomize() )\n";
5468
        print FH "      `uvm_error(\"${tb_module_name}\", \"Failed to randomize top-level configuration object\" )\n";
5469
        print FH "\n";
5470
 
5471
        foreach ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) {
5472
            my $agent = $agent_list[$i];
5473
 
5474
            for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) {
5475
                my $suffix = calc_suffix($j, $number_of_instances{$agent});
5476
 
5477
                my $test_harness_name;
5478
                if ( $dual_top eq "YES" ) {
5479
                    $test_harness_name = ${th_module_name};
5480
                }
5481
                else {
5482
                    $test_harness_name = "th";
5483
                }
5484
 
5485
                if ( defined $nested_config_objects && $nested_config_objects eq "YES" ) {
5486
                    unless ( exists $generate_interface_instance{$agent} && $generate_interface_instance{$agent} eq "NO" ) {
5487
                        align("    top_env_config.m_${agent}${suffix}_config.vif ", "= $test_harness_name.$all_agent_ifs[$i]_${j};", "");
5488
                    }
5489
                }
5490
                else {
5491
                    unless ( exists $generate_interface_instance{$agent} && $generate_interface_instance{$agent} eq "NO" ) {
5492
                        align("    top_env_config.${agent}${suffix}_vif ", "= $test_harness_name.$all_agent_ifs[$i]_${j};", "");
5493
                    }
5494
                    my $value;
5495
                    if ( exists $agent_is_active{$agent} ) {
5496
                        $value = "$agent_is_active{$agent}";
5497
                    }
5498
                    else {
5499
                        $value = "UVM_ACTIVE";
5500
                    }
5501
                    align("    top_env_config.is_active_${agent}${suffix} ", "= ${value};", "");
5502
 
5503
                    if ( exists $agent_checks_enable{$agent} and $agent_checks_enable{$agent} eq "NO" ) {
5504
                        $value = "0";
5505
                    }
5506
                    else {
5507
                        $value = "1";
5508
                    }
5509
                    align("    top_env_config.checks_enable_${agent}${suffix} ", "= ${value};", "");
5510
 
5511
                    if ( exists $agent_coverage_enable{$agent} and $agent_coverage_enable{$agent} eq "NO" ) {
5512
                        $value = "0";
5513
                    }
5514
                    else {
5515
                        $value = "1";
5516
                    }
5517
                    align("    top_env_config.coverage_enable_${agent}${suffix} ", "= ${value};", "");
5518
                    align("\n", "", "");
5519
                }
5520
            }
5521
        }
5522
 
5523
        gen_aligned();
5524
 
5525
        print FH "\n";
5526
        print FH "    uvm_config_db #(${tbname}_config)::set(null, \"uvm_test_top\", \"config\", top_env_config);\n";
5527
        print FH "    uvm_config_db #(${tbname}_config)::set(null, \"uvm_test_top.m_env\", \"config\", top_env_config);\n";
5528
        print FH "\n";
5529
 
5530
        insert_inc_file("    ", $tb_inc_before_run_test, $tb_inc_before_run_test_inline, "tb_inc_before_run_test", $common_tpl_fname);
5531
 
5532
        print FH "    run_test();\n";
5533
        print FH "  end\n";
5534
        print FH "\n";
5535
    }
5536
    print FH "endmodule\n";
5537
    print FH "\n";
5538
    close(FH);
5539
}
5540
 
5541
sub gen_regmodel_pkg {
5542
 
5543
    my $line;
5544
    print LOGFILE "\nProcessing register layer\n";
5545
    my $dir = $project . "/tb/regmodel";
5546
    printf LOGFILE "rdir: $dir\n";
5547
    mkdir( $dir, 0755 );
5548
    my $file1 = "./${regmodel_file}";
5549
    my $file2 = $project . "/tb/regmodel/${regmodel_file}";
5550
    print LOGFILE "file1: $file1\n";
5551
    print LOGFILE "file2: $file2\n";
5552
 
5553
    #open regmodel file and  put into package
5554
    open( REGFILE_IN, "<" . $file1 )
5555
      || die "Exiting due to Error: can't open $file1";
5556
    open( REGFILE_OUT, ">" . $file2 )
5557
      || die "Exiting due to Error: can't open $file2";
5558
    my $guard_macro = "";
5559
    COPY_HEADER: {
5560
        $line = <REGFILE_IN>;
5561
 
5562
        #write header without modification
5563
        if ( $line =~ /^\s*$|^\s*\/\/.*$|^\s*\/\*.*$|^\s*`ifndef\s+([\w_]+).*/ )
5564
        {
5565
            #blank line|comment|compiler directive
5566
            if ($1) { $guard_macro = $1; }
5567
            print REGFILE_OUT $line;
5568
            redo COPY_HEADER;
5569
        }
5570
    }
5571
    print REGFILE_OUT "package regmodel_pkg;\n";
5572
    print REGFILE_OUT "\n";
5573
    print REGFILE_OUT "import uvm_pkg::*;\n";
5574
    print REGFILE_OUT "`include \"uvm_macros.svh\"\n";
5575
    print REGFILE_OUT "\n";
5576
    print REGFILE_OUT "$line";
5577
    while ( $line = <REGFILE_IN> ) {
5578
 
5579
        #copy rest of package file
5580
        last if ( $line =~ /\s*`endif\s+$guard_macro/ );
5581
        print REGFILE_OUT $line;
5582
    }
5583
    print REGFILE_OUT "\n";
5584
    print REGFILE_OUT "endpackage: regmodel_pkg\n";
5585
    print REGFILE_OUT "\n";
5586
    print REGFILE_OUT $line if $line;
5587
    close(REGFILE_IN);
5588
    close(REGFILE_OUT);
5589
}
5590
 
5591
sub gen_regmodel_adapter {
5592
    $dir = $project . "/tb/" . $agent_name;
5593
    open( FH, ">" . $dir . "/sv/reg2" . $agent_name . "_adapter.sv" )
5594
      || die "Exiting due to Error: can't open adapter: reg2${agent_name}_adapter.sv";
5595
 
5596
    write_file_header "${agent_name}_adapter.sv", "Environment for reg2 ${agent_name}_adapter.sv\n";
5597
 
5598
    print FH "`ifndef REG2" . uc($agent_name) . "_ADAPTER_SV\n";
5599
    print FH "`define REG2" . uc($agent_name) . "_ADAPTER_SV\n";
5600
    print FH "\n";
5601
    insert_inc_file("", $agent_adapter_inc_before_class{$agent_name}, $agent_adapter_inc_before_inline{$agent_name}, "adapter_inc_before_class", $tpl_fname{$agent_name});
5602
 
5603
    print FH "class reg2${agent_name}_adapter extends uvm_reg_adapter;\n";
5604
    print FH "\n";
5605
    print FH "  `uvm_object_utils(reg2" . $agent_name . "_adapter)\n";
5606
    print FH "\n";
5607
    print FH "  extern function new(string name = \"\");\n";
5608
    print FH "\n";
5609
 
5610
    unless ( exists $agent_adapter_generate_methods_inside_class{$agent_name} && $agent_adapter_generate_methods_inside_class{$agent_name} eq "NO" )
5611
    {
5612
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
5613
            print FH "  // You can remove reg2bus and bus2reg by setting adapter_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n";
5614
        }
5615
        print FH "  extern function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);\n";
5616
        print FH "  extern function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);\n";
5617
        print FH "\n";
5618
    }
5619
 
5620
    insert_inc_file("  ", $agent_adapter_inc_inside_class{$agent_name}, $agent_adapter_inc_inside_inline{$agent_name}, "adapter_inc_inside_class", $tpl_fname{$agent_name});
5621
 
5622
    print FH "endclass : reg2" . $agent_name . "_adapter \n";
5623
    print FH "\n";
5624
    print FH "\n";
5625
    print FH "function reg2${agent_name}_adapter::new(string name = \"\");\n";
5626
    print FH "   super.new(name);\n";
5627
    print FH "endfunction : new\n";
5628
    print FH "\n";
5629
    print FH "\n";
5630
 
5631
    unless ( exists $agent_adapter_generate_methods_after_class{$agent_name} && $agent_adapter_generate_methods_after_class{$agent_name} eq "NO" )
5632
    {
5633
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
5634
            print FH "// You can remove reg2bus and bus2reg by setting adapter_generate_methods_after_class = no in file $tpl_fname{$agent_name}\n\n";
5635
        }
5636
        print FH "function uvm_sequence_item reg2${agent_name}_adapter::reg2bus(const ref uvm_reg_bus_op rw);\n";
5637
        print FH "  $agent_item_types{$agent_name} ${agent_name} = $agent_item_types{$agent_name}::type_id::create(\"${agent_name}\");\n";
5638
 
5639
        if ( $reg_access_mode{$agent_name} =~ /WR|WO/i ) {
5640
            align("  $agent_name.$bus2reg_map{$agent_name}->{'kind'} ", "= (rw.kind == UVM_READ) ? 0 : 1;", "");
5641
            align("  $agent_name.$bus2reg_map{$agent_name}->{'addr'} ", "= rw.addr;", "");
5642
            align("  $agent_name.$bus2reg_map{$agent_name}->{'data'} ", "= rw.data;", "");
5643
 
5644
            gen_aligned();
5645
 
5646
            print FH "  `uvm_info(get_type_name(), \$sformatf(\"reg2bus rw::kind: %s, addr: %d, data: %h, status: %s\", rw.kind, rw.addr, rw.data, rw.status), UVM_HIGH)\n";
5647
        }
5648
        elsif ( $reg_access_mode{$agent_name} =~ /RO/i ) {
5649
            align("  $agent_name.$bus2reg_map{$agent_name}->{'kind'} ", "= (rw.kind == UVM_READ) ? 0 : 1;", "");
5650
            align("  $agent_name.$bus2reg_map{$agent_name}->{'addr'} ", "= rw.addr;", "");
5651
            align("  $agent_name.$bus2reg_map{$agent_name}->{'data'} ", "= rw.data;", "");
5652
 
5653
            gen_aligned();
5654
 
5655
            print FH "  `uvm_info(get_type_name(), \$sformatf(\"reg2bus rw::kind: %s, addr: %d, data: %h, status: %s\", rw.kind, rw.addr, rw.data, rw.status), UVM_HIGH)\n";
5656
            print FH "  if (rw.kind != UVM_READ) `uvm_warning(get_type_name(), \"Interface is READ-ONLY\")\n";
5657
        }
5658
        else {
5659
            warning_prompt("reg_access_mode is neither WR, WO, nor RO, so reg2${agent_name}_adapter is incomplete");
5660
            print FH "  `uvm_warning(get_type_name(), \"Interface mode not specified\")\n";
5661
        }
5662
 
5663
        print FH "  return " . $agent_name . ";\n";
5664
        print FH "endfunction : reg2bus\n";
5665
        print FH "\n";
5666
        print FH "\n";
5667
        print FH "function void reg2${agent_name}_adapter::bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);\n";
5668
        print FH "  $agent_item_types{$agent_name} ${agent_name};\n";
5669
        print FH "  if (!\$cast(${agent_name}, bus_item))\n";
5670
        print FH "    `uvm_fatal(get_type_name(),\"Provided bus_item is not of the correct type\")\n";
5671
 
5672
        if ( $reg_access_mode{$agent_name} =~ /WR|WO/i ) {
5673
            print FH "  rw.kind   = $agent_name.$bus2reg_map{$agent_name}->{'kind'}" . " ? UVM_WRITE : UVM_READ;\n";
5674
        }
5675
        else {
5676
            print FH "  rw.kind = UVM_READ;\n";
5677
        }
5678
        print FH "  rw.addr   = $agent_name.$bus2reg_map{$agent_name}->{'addr'};\n";
5679
        print FH "  rw.data   = $agent_name.$bus2reg_map{$agent_name}->{'data'};\n";
5680
        print FH "  rw.status = UVM_IS_OK;\n";
5681
        print FH "  `uvm_info(get_type_name(), \$sformatf(\"bus2reg rw::kind: %s, addr: %d, data: %h, status: %s\", rw.kind, rw.addr, rw.data, rw.status), UVM_HIGH)\n";
5682
        print FH "endfunction : bus2reg\n";
5683
        print FH "\n";
5684
        print FH "\n";
5685
    }
5686
    insert_inc_file("", $agent_adapter_inc_after_class{$agent_name}, $agent_adapter_inc_after_inline{$agent_name}, "adapter_inc_after_class", $tpl_fname{$agent_name});
5687
    print FH "\n";
5688
    print FH "`endif // REG2" . uc($agent_name) . "_ADAPTER_SV\n";
5689
    print FH "\n";
5690
    close(FH);
5691
}
5692
 
5693
sub gen_regmodel_coverage {
5694
    $dir = $project . "/tb/" . $agent_name;
5695
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_env_coverage.sv" )
5696
      || die "Exiting due to Error: can't open config: ${agent_name}_env_coverage.sv";
5697
 
5698
    write_file_header "${agent_name}_env_coverage.sv", "Coverage for $agent_name env\n";
5699
 
5700
    print FH "`ifndef " . uc($agent_name) . "_ENV_COVERAGE_SV\n";
5701
    print FH "`define " . uc($agent_name) . "_ENV_COVERAGE_SV\n";
5702
    print FH "\n";
5703
 
5704
    insert_inc_file("", $reg_cover_inc_before_class{$agent_name}, $reg_cover_inc_before_inline{$agent_name}, "reg_cover_inc_before_class", $tpl_fname{$agent_name});
5705
 
5706
    print FH "class ${agent_name}_env_coverage extends uvm_subscriber #($agent_item_types{$agent_name});\n";
5707
    print FH "\n";
5708
    print FH "  `uvm_component_utils(" . $agent_name . "_env_coverage)\n";
5709
    print FH "\n";
5710
 
5711
    align("  ${agent_name}_config ", "m_config;", "");
5712
    align("  bit  ", "m_is_covered;", "");
5713
    align("  $agent_item_types{$agent_name}  ", "m_item;", "");
5714
    align("  $reg_access_block_type{$agent_name}  ", "regmodel;\n", "");
5715
 
5716
    gen_aligned();
5717
 
5718
    #if include file for coverage collector exists, pull it in here, otherwise
5719
    #create covergroup and coverpoints with default bins
5720
    if ( exists $reg_cover_inc{$agent_name}
5721
        && -e "${project}/tb/include/$reg_cover_inc{$agent_name}" )
5722
    {
5723
             open(FH_COV, "<${project}/tb/include/$reg_cover_inc{$agent_name}") or die "CANNOT OPEN INCLUDE FILE reg_cover_inc{$agent_name}";
5724
            my $cov_inc = join("",<FH_COV>);
5725
            #check that file contains covergroup named "m_cov"
5726
            if ($cov_inc =~ /covergroup\s+m_cov(\s|;)/) {
5727
            print FH "  // Inserting covergroup from include file\n";
5728
            insert_inc_file("  ", $reg_cover_inc{$agent_name}, $reg_cover_inc_inline{$agent_name}, "", "");
5729
        }
5730
        else
5731
        {
5732
                warn "WARNING. The file reg_cover_inc = $reg_cover_inc{$agent_name} should contain a covergroup named m_cov. Since it does not, it is assumed to contain only coverpoints. This still works but is deprecated, so you should modify the include file to contain the whole covergroup";
5733
            print FH "  covergroup m_cov;\n";
5734
            print FH "    option.per_instance = 1;\n";
5735
            print FH "    // Inserting coverpoints from include file\n";
5736
            insert_inc_file("    ", $reg_cover_inc{$agent_name}, $reg_cover_inc_inline{$agent_name}, "", "");
5737
            print FH "  endgroup: m_cov\n";
5738
            print FH "\n";
5739
        }
5740
    }
5741
    else {
5742
        unless ( exists $reg_cover_generate_methods_inside_class{$agent_name} && $reg_cover_generate_methods_inside_class{$agent_name} eq "NO" )
5743
        {
5744
            unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
5745
                print FH "  // You can replace covergroup m_cov by setting reg_cover_inc in file $tpl_fname{$agent_name}\n";
5746
                print FH "  // or remove covergroup m_cov by setting reg_cover_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n";
5747
            }
5748
            print FH "  covergroup m_cov;\n";
5749
            print FH "    option.per_instance = 1;\n";
5750
            print FH "    // You may insert additional coverpoints here ...\n";
5751
            print FH "\n";
5752
            print FH "  endgroup\n";
5753
            print FH "\n";
5754
        }
5755
    }
5756
 
5757
    unless ( exists $reg_cover_generate_methods_inside_class{$agent_name} && $reg_cover_generate_methods_inside_class{$agent_name} eq "NO" )
5758
    {
5759
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
5760
            print FH "  // You can remove new, write, and report_phase by setting reg_cover_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n";
5761
        }
5762
        print FH "  extern function new(string name, uvm_component parent);\n";
5763
        print FH "  extern function void write($agent_item_types{$agent_name} t);\n";
5764
        print FH "  extern function void build_phase(uvm_phase phase);\n";
5765
        print FH "  extern function void report_phase(uvm_phase phase);\n";
5766
        print FH "\n";
5767
    }
5768
 
5769
    insert_inc_file("  ", $reg_cover_inc_inside_class{$agent_name}, $reg_cover_inc_inside_inline{$agent_name}, "reg_cover_inc_inside_class", $tpl_fname{$agent_name});
5770
 
5771
    print FH "endclass : " . $agent_name . "_env_coverage \n";
5772
    print FH "\n";
5773
    print FH "\n";
5774
 
5775
    unless ( exists $reg_cover_generate_methods_after_class{$agent_name} && $reg_cover_generate_methods_after_class{$agent_name} eq "NO" )
5776
    {
5777
        unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) {
5778
            print FH "// You can remove new, write, and report_phase by setting reg_cover_generate_methods_after_class = no in file $tpl_fname{$agent_name}\n\n";
5779
        }
5780
        print FH "function ${agent_name}_env_coverage::new(string name, uvm_component parent);\n";
5781
        print FH "  super.new(name, parent);\n";
5782
        print FH "  m_cov = new();\n";
5783
        print FH "endfunction : new\n";
5784
        print FH "\n";
5785
        print FH "\n";
5786
        print FH "function void ${agent_name}_env_coverage::write($agent_item_types{$agent_name} t);\n";
5787
        print FH "  // Assign seq item properties to member variables\n";
5788
        print FH "  m_item = t;\n";
5789
        print FH "  m_cov.sample();\n";
5790
        print FH "  // Check coverage - could use m_cov.option.goal instead of 100 if your simulator supports it\n";
5791
        print FH "  if (m_cov.get_inst_coverage() >= 100) m_is_covered = 1;\n";
5792
        print FH "endfunction : write\n";
5793
        print FH "\n";
5794
        print FH "\n";
5795
        print FH "function void ${agent_name}_env_coverage::build_phase(uvm_phase phase);\n";
5796
        print FH "  if (!uvm_config_db #(${agent_name}_config)::get(this, \"\", \"config\", m_config))\n";
5797
        print FH "    `uvm_error(get_type_name(), \"${agent_name} config not found\")\n";
5798
        print FH "endfunction : build_phase\n";
5799
        print FH "\n";
5800
        print FH "\n";
5801
        print FH "function void ${agent_name}_env_coverage::report_phase(uvm_phase phase);\n";
5802
        print FH "  if (m_config.coverage_enable)\n";
5803
        print FH "    `uvm_info(get_type_name(), \$sformatf(\"Coverage score = %3.1f%%\", m_cov.get_inst_coverage()), UVM_MEDIUM)\n";
5804
        print FH "  else\n";
5805
        print FH "    `uvm_info(get_type_name(), \"Coverage disabled for this agent\", UVM_MEDIUM)\n";
5806
        print FH "endfunction : report_phase\n";
5807
        print FH "\n";
5808
        print FH "\n";
5809
    }
5810
 
5811
    insert_inc_file("", $reg_cover_inc_after_class{$agent_name}, $reg_cover_inc_after_inline{$agent_name}, "reg_cover_inc_after_class", $tpl_fname{$agent_name});
5812
 
5813
    print FH "`endif // " . uc($agent_name) . "_ENV_COVERAGE_SV\n";
5814
    print FH "\n";
5815
    close(FH);
5816
}
5817
 
5818
sub gen_regmodel_seq_lib {
5819
    $dir = $project . "/tb/" . $agent_name;
5820
    open( FH, ">" . $dir . "/sv/" . $agent_name . "_env_seq_lib.sv" )
5821
      || die "Exiting due to Error: can't open seq_lib: " . $agent_name . "_env_seq_lib.sv";
5822
 
5823
    write_file_header "${agent_name}_env_seq_lib.sv", "Sequence for $agent_name env\n";
5824
 
5825
    print FH "`ifndef " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n";
5826
    print FH "`define " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n";
5827
    print FH "\n";
5828
 
5829
    print FH "class ${agent_name}_env_default_seq extends uvm_sequence #($agent_item_types{$agent_name});\n";
5830
    print FH "\n";
5831
    print FH "  `uvm_object_utils(" . $agent_name . "_env_default_seq)\n";
5832
    print FH "\n";
5833
 
5834
    for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) {
5835
        my $suffix = calc_suffix($i, $number_of_instances{$agent_name});
5836
 
5837
        align("  $reg_access_block_type{$agent_name} ", "regmodel${suffix};", "");
5838
        align("  ${agent_name}_config ", "m_config${suffix};", "");
5839
    }
5840
    align("\n", "", "");
5841
    align("  uvm_status_e ", "status;", "// Returning access status");
5842
    align("  rand uvm_reg_data_t ", "data;", "// For passing data");
5843
 
5844
    gen_aligned();
5845
 
5846
    print FH "\n";
5847
    print FH "  extern function new(string name = \"\");\n";
5848
    print FH "  extern task body();\n";
5849
    print FH "\n";
5850
    print FH "`ifndef UVM_POST_VERSION_1_1\n";
5851
    print FH "  // Functions to support UVM 1.2 objection API in UVM 1.1\n";
5852
    print FH "  extern function uvm_phase get_starting_phase();\n";
5853
    print FH "  extern function void set_starting_phase(uvm_phase phase);\n";
5854
    print FH "`endif\n";
5855
    print FH "\n";
5856
    print FH "endclass : " . $agent_name . "_env_default_seq\n";
5857
    print FH "\n";
5858
    print FH "\n";
5859
    print FH "function ${agent_name}_env_default_seq::new(string name = \"\");\n";
5860
    print FH "  super.new(name);\n";
5861
    print FH "endfunction : new\n";
5862
    print FH "\n";
5863
    print FH "\n";
5864
    print FH "task ${agent_name}_env_default_seq::body();\n";
5865
    print FH "  `uvm_info(get_type_name(), \"Default sequence starting\", UVM_HIGH)\n";
5866
    print FH "\n";
5867
 
5868
    my $n = $number_of_instances{$agent_name};
5869
    print FH "  fork\n" if $n > 1;
5870
 
5871
    for ( my $i = 0 ; $i < $n ; $i++ ) {
5872
        my $suffix = calc_suffix($i, $n);
5873
 
5874
        print FH "  begin\n";
5875
        print FH "    uvm_reg      data_regs[\$];\n";
5876
        print FH "    regmodel${suffix}.get_registers(data_regs);\n";
5877
        print FH "    data_regs.shuffle();\n";
5878
        print FH "    foreach(data_regs[i])\n";
5879
        print FH "    begin\n";
5880
        print FH "      // Randomize register content and then update\n";
5881
        print FH "      if ( !data_regs[i].randomize() )\n";
5882
        print FH "        `uvm_error(get_type_name(), \$sformatf(\"Failed to randomize data_regs[%0d]\", i))\n";
5883
        print FH "      data_regs[i].update(status, .path(UVM_FRONTDOOR), .parent(this));\n";
5884
        print FH "    end\n";
5885
        print FH "  end\n"
5886
 
5887
    }
5888
    print FH "  join\n" if $n > 1;
5889
    print FH "\n";
5890
    print FH "  `uvm_info(get_type_name(), \"Default sequence completed\", UVM_HIGH)\n";
5891
    print FH "endtask : body\n";
5892
    print FH "\n";
5893
    print FH "\n";
5894
 
5895
    print FH "`ifndef UVM_POST_VERSION_1_1\n";
5896
    print FH "function uvm_phase ${agent_name}_env_default_seq::get_starting_phase();\n";
5897
    print FH "  return starting_phase;\n";
5898
    print FH "endfunction: get_starting_phase\n";
5899
    print FH "\n";
5900
    print FH "\n";
5901
    print FH "function void ${agent_name}_env_default_seq::set_starting_phase(uvm_phase phase);\n";
5902
    print FH "  starting_phase = phase;\n";
5903
    print FH "endfunction: set_starting_phase\n";
5904
    print FH "`endif\n";
5905
    print FH "\n";
5906
    print FH "\n";
5907
 
5908
    insert_inc_file("", $agent_env_seq_inc{$agent_name}, $agent_env_seq_inc_inline{$agent_name}, "agent_env_seq_inc", $tpl_fname{$agent_name});
5909
 
5910
    print FH "`endif // " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n";
5911
    print FH "\n";
5912
 
5913
    close(FH);
5914
}
5915
 
5916
sub deal_with_files_f {
5917
    if ( open( FILESFH, "<", "${dut_path}/files.f") ) {
5918
        # files.f already exists in DUT directory
5919
        close(FILESFH);
5920
    }
5921
    else {
5922
        # files.f does not exist, so create files.f in the output directory
5923
        open( FILESFH, ">", "${dut_tb_path}/files.f");
5924
        opendir( DH, $dut_path ) or die "Unable to open DUT directory ${dut_path} when looking for DUT files.f\n";
5925
        while (my $file = readdir(DH)) {
5926
            if ( $file =~ /.*\.sv/ ) {
5927
                print FILESFH "${file}\n";
5928
            }
5929
        }
5930
        closedir(DH);
5931
        close(FILESFH);
5932
    }
5933
}
5934
 
5935
sub gen_questa_script {
5936
    $dir = $project . "/sim";
5937
    open( FH, ">" . $dir . "/compile_questa.do" )
5938
      || die "Exiting due to Error: can't open file: compile_questa.do";
5939
    print FH "\n";
5940
    print FH "file delete -force work\n\n";
5941
    print FH "vlib work\n\n";
5942
    print FH "#compile the dut code\n";
5943
    print FH "set cmd \"vlog -F ../${dut_tb_dir}/files.f\"\n";
5944
    print FH "eval \$cmd\n\n";
5945
 
5946
    if($common_pkg_fname) {
5947
        open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f";
5948
        do {
5949
            print FH "set cmd \"vlog -sv ../${dut_tb_dir}/${common_pkg_fname}\"\n";
5950
            print FH "eval \$cmd\n\n";
5951
        } unless (grep /$common_pkg_fname/,<FFH>);
5952
         close FFH;
5953
    }
5954
 
5955
    do {
5956
        print FH "#compile the register model package\n";
5957
        print FH "set cmd \"vlog -sv  ../tb/regmodel/${regmodel_file}\"\n";
5958
        print FH "eval \$cmd\n\n";
5959
    } if $regmodel;
5960
 
5961
    print FH "set tb_name $tbname\n";
5962
    $incdir = "+incdir+../tb/include ";
5963
    foreach my $inc_path ( @inc_path_list ) {
5964
        if ( $inc_path ne "" ) {
5965
            $incdir .= "+incdir+" . $inc_path . " ";
5966
        }
5967
    }
5968
 
5969
    if($common_env_pkg_fname) {
5970
        open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f";
5971
        do {
5972
            print FH "set cmd \"vlog -sv " . $incdir . " ../tb/include/${common_env_pkg_fname}\"\n";
5973
            print FH "eval \$cmd\n\n";
5974
        } unless (grep /$common_env_pkg_fname/,<FFH>);
5975
         close FFH;
5976
    }
5977
 
5978
    print FH "set agent_list {\\ \n";
5979
    print LOGFILE "env_list=@env_list, agent_list=@agent_list,\n";
5980
    foreach my $aname (@stand_alone_agents) {
5981
        if ( $aname ne "" ) {
5982
            print FH "    $aname \\\n";
5983
        }
5984
    }
5985
    foreach my $agent (@agent_list) {
5986
        if ( !grep( /$agent/, @stand_alone_agents ) ) {
5987
            print FH "    $agent \\\n";
5988
        }
5989
    }
5990
    print FH "}\n";
5991
 
5992
    print FH "foreach  ele \$agent_list {\n";
5993
    print FH "  if {\$ele != \" \"} {\n";
5994
    print FH "    set cmd  \"vlog -sv " . $incdir . "+incdir+../tb/\"\n";
5995
    print FH "    append cmd \$ele \"/sv ../tb/\" \$ele \"/sv/\" \$ele \"_pkg.sv\ ../tb/\" \$ele \"/sv/\" \$ele \"_if.sv\"\n";
5996
 
5997
    if ( $split_transactors eq "YES") {
5998
        print FH "    append cmd \" ../tb/\" \$ele \"/sv/\" \$ele \"_bfm.sv\"\n";
5999
    }
6000
 
6001
    print FH "    eval \$cmd\n";
6002
    print FH "  }\n";
6003
    print FH "}\n\n";
6004
 
6005
    if ( defined $syosil_scoreboard_src_path ) {
6006
        print FH "set cmd  \"vlog -sv +incdir+../../$syosil_scoreboard_src_path ../../$syosil_scoreboard_src_path/pk_syoscb.sv\"\n";
6007
        print FH "eval \$cmd\n\n";
6008
    }
6009
 
6010
    print FH "set cmd  \"vlog -sv " . $incdir . "+incdir+../tb/\"\n";
6011
    print FH "append cmd \$tb_name \"/sv ../tb/\" \$tb_name \"/sv/\" \$tb_name \"_pkg.sv\"\n";
6012
    print FH "eval \$cmd\n\n";
6013
 
6014
    print FH "set cmd  \"vlog -sv " . $incdir . "+incdir+../tb/\"\n";
6015
    print FH "append cmd \$tb_name \"_test/sv ../tb/\" \$tb_name \"_test/sv/\" \$tb_name \"_test_pkg.sv\"\n";
6016
    print FH "eval \$cmd\n\n";
6017
 
6018
    print FH "set cmd  \"vlog -sv -timescale $timeunit/$timeprecision "
6019
      . $incdir
6020
      . "+incdir+../tb/\"\n";
6021
    print FH "append cmd \$tb_name \"_tb/sv ../tb/\" \$tb_name \"_tb/sv/\" \$tb_name \"_th.sv\"\n";
6022
    print FH "eval \$cmd\n\n";
6023
 
6024
    print FH "set cmd  \"vlog -sv -timescale $timeunit/$timeprecision "
6025
      . $incdir
6026
      . "+incdir+../tb/\"\n";
6027
    print FH "append cmd \$tb_name \"_tb/sv ../tb/\" \$tb_name \"_tb/sv/\" \$tb_name \"_tb.sv\"\n";
6028
    print FH "eval \$cmd\n\n";
6029
 
6030
    print FH "vsim ${tb_module_name} ";
6031
    if ( $dual_top eq "YES" ) {
6032
        print FH "${th_module_name} ";
6033
    }
6034
    print FH "+UVM_TESTNAME=${tbname}_test ${uvm_cmdline} -voptargs=+acc -solvefaildebug -uvmcontrol=all -classdebug\n";
6035
    print FH "run 0\n";
6036
    print FH "#do wave.do\n";
6037
    close(FH);
6038
 
6039
    ### add execute permissions for script
6040
    chmod( 0755, $dir . "/compile_questa.do" );
6041
}
6042
 
6043
sub gen_vcs_script {
6044
    my $dir = $project . "/sim";
6045
    my $vcs_opts =
6046
      "-sverilog +acc +vpi -timescale=$timeunit/$timeprecision -ntb_opts uvm-1.2";
6047
    open( FH, ">" . $dir . "/compile_vcs.sh" )
6048
      || die "Exiting due to Error: can't open file: compile_vcs.sh";
6049
    print FH "#!/bin/sh\n";
6050
    print FH "vcs $vcs_opts \\\n";
6051
    gen_compile_file_list();
6052
    print FH "-R +UVM_TESTNAME=${tbname}_test ${uvm_cmdline} \$* \n";
6053
    close(FH);
6054
 
6055
    ### add execute permissions for script
6056
    chmod( 0755, $dir . "/compile_vcs.sh" );
6057
}
6058
 
6059
sub gen_ius_script {
6060
    my $dir = $project . "/sim";
6061
    my $ius_opts =
6062
      "-vtimescale $timeunit/$timeprecision -uvmhome \${IUS_HOME}/tools/methodology/UVM/CDNS-1.2";
6063
    open( FH, ">" . $dir . "/compile_ius.sh" )
6064
      || die "Exiting due to Error: can't open file: compile_ius.sh";
6065
    print FH "#!/bin/sh\n";
6066
    print FH "IUS_HOME=`ncroot`\n";
6067
    print FH "irun $ius_opts \\\n";
6068
    gen_compile_file_list();
6069
    print FH "+UVM_TESTNAME=${tbname}_test ${uvm_cmdline} \$* \n";
6070
    close(FH);
6071
 
6072
    ### add execute permissions for script
6073
    chmod( 0755, $dir . "/compile_ius.sh" );
6074
}
6075
 
6076
sub gen_riviera_script {
6077
    $dir = $project . "/sim";
6078
    open( FH, ">" . $dir . "/compile_riviera.do" )
6079
      || die "Exiting due to Error: can't open file: compile_riviera.do";
6080
    print FH "\n";
6081
    print FH "file delete -force work\n\n";
6082
    print FH "alib work\n\n";
6083
    print FH "# Compile the dut code\n";
6084
 
6085
    print FH "#set cmd \"alog -uvm -F ../${dut_tb_dir}/files.f\"  # Previous version using UVM 1.1d\n";
6086
    print FH "set cmd \"alog +incdir+\$aldec/vlib/uvm-1.2/src -l uvm_1_2 -err VCP5417 W9 -err VCP3003 W9 -err VCP2129 W9 -F ../${dut_tb_dir}/files.f\"\n";
6087
 
6088
    print FH "eval \$cmd\n\n";
6089
 
6090
    print FH "#set cmd \"alog -uvm \"  # Previous version using UVM 1.1d\n";
6091
    print FH "set cmd \"alog +incdir+\$aldec/vlib/uvm-1.2/src -l uvm_1_2 -err VCP5417 W9 -err VCP3003 W9 -err VCP2129 W9 \"\n";
6092
 
6093
    if($common_pkg_fname) {
6094
        open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f";
6095
        do {
6096
        print FH "\n# Compile the common package\n";
6097
            print FH "append cmd \" ../${dut_tb_dir}/${common_pkg_fname}\"\n";
6098
        } unless (grep /$common_pkg_fname/,<FFH>);
6099
         close FFH;
6100
    }
6101
 
6102
    do {
6103
        print FH "\n# Compile the register model package\n";
6104
        print FH "append cmd \"  ../tb/regmodel/${regmodel_file}\"\n";
6105
    } if $regmodel;
6106
 
6107
    print FH "\nset tb_name $tbname\n";
6108
    $incdir = "+incdir+../tb/include ";
6109
    foreach my $inc_path ( @inc_path_list  ) {
6110
        if ( $inc_path ne "" ) {
6111
            $incdir .= "+incdir+" . $inc_path . " ";
6112
        }
6113
    }
6114
    print FH "append cmd \" " . $incdir . "\"\n";
6115
 
6116
    if($common_env_pkg_fname) {
6117
        open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f";
6118
        do {
6119
            print FH "\n# Compile the common env package\n";
6120
            print FH "append cmd \" ../tb/include/${common_env_pkg_fname}\"\n";
6121
        } unless (grep /$common_env_pkg_fname/,<FFH>);
6122
         close FFH;
6123
    }
6124
 
6125
    print FH "\n# Compile the agents\n";
6126
    print FH "set agent_list {\\ \n";
6127
    print LOGFILE "env_list=@env_list, agent_list=@agent_list,\n";
6128
    foreach my $aname (@stand_alone_agents) {
6129
        if ( $aname ne "" ) {
6130
            print FH "    $aname \\\n";
6131
        }
6132
    }
6133
    foreach my $agent (@agent_list) {
6134
        if ( !grep( /$agent/, @stand_alone_agents ) ) {
6135
            print FH "    $agent \\\n";
6136
        }
6137
    }
6138
    print FH "}\n";
6139
 
6140
    print FH "foreach  ele \$agent_list {\n";
6141
    print FH "  if {\$ele != \" \"} {\n";
6142
    print FH "    append cmd \" +incdir+../tb/\" \$ele \"/sv ../tb/\" \$ele \"/sv/\" \$ele \"_pkg.sv\ ../tb/\" \$ele \"/sv/\" \$ele \"_if.sv\"\n";
6143
    if ( $split_transactors eq "YES") {
6144
        print FH "    append cmd \" ../tb/\" \$ele \"/sv/\" \$ele \"_bfm.sv\"\n";
6145
    }
6146
    print FH "  }\n";
6147
    print FH "}\n";
6148
 
6149
    if ( defined $syosil_scoreboard_src_path ) {
6150
        print FH "\n# Compile the Syosil scoreboard\n";
6151
        print FH "append cmd  \" +incdir+../../$syosil_scoreboard_src_path ../../$syosil_scoreboard_src_path/pk_syoscb.sv\"\n";
6152
    }
6153
 
6154
    print FH "\n# Compile the test and the modules\n";
6155
    print FH "append cmd \" +incdir+../tb/\" \$tb_name \"/sv\"\n";
6156
    print FH "append cmd \" ../tb/\" \$tb_name \"/sv/\" \$tb_name \"_pkg.sv\"\n";
6157
    print FH "append cmd \" ../tb/\" \$tb_name \"_test/sv/\" \$tb_name \"_test_pkg.sv\"\n";
6158
    print FH "append cmd \" ../tb/\" \$tb_name \"_tb/sv/\" \$tb_name \"_th.sv\"\n";
6159
    print FH "append cmd \" ../tb/\" \$tb_name \"_tb/sv/\" \$tb_name \"_tb.sv\"\n";
6160
    print FH "eval \$cmd\n\n";
6161
 
6162
    print FH "asim ${tb_module_name} ";
6163
    if ( $dual_top eq "YES" ) {
6164
        print FH "${th_module_name} ";
6165
    }
6166
    print FH "+UVM_TESTNAME=${tbname}_test ${uvm_cmdline} -voptargs=+acc -solvefaildebug -uvmcontrol=all -classdebug\n";
6167
    print FH "run -all\n";
6168
    print FH "quit\n";
6169
    close(FH);
6170
 
6171
    ### add execute permissions for script
6172
    chmod( 0755, $dir . "/compile_riviera.do" );
6173
}
6174
 
6175
sub gen_compile_file_list {
6176
    my $incdir = "+incdir+../tb/include \\\n";
6177
    foreach my $inc_path ( @inc_path_list ) {
6178
        if ( $inc_path ne "" ) {
6179
            $incdir .= "+incdir+$inc_path \\\n";
6180
        }
6181
    }
6182
#    $incdir .= "+incdir+../tb/${tbname}_common/sv \\\n";
6183
 
6184
    foreach my $aname (@stand_alone_agents) {
6185
        if ( $aname ne "" ) {
6186
            $incdir .= "+incdir+../tb/${aname}/sv \\\n";
6187
        }
6188
    }
6189
    foreach my $agent (@agent_list) {
6190
        if ( !grep( /$agent/, @stand_alone_agents ) ) {
6191
            $incdir .= "+incdir+../tb/${agent}/sv \\\n";
6192
        }
6193
    }
6194
 
6195
    if ( defined $syosil_scoreboard_src_path ) {
6196
        $incdir .= "+incdir+../../${syosil_scoreboard_src_path}\\\n";
6197
    }
6198
    $incdir .= "+incdir+../tb/${tbname}/sv \\\n";
6199
    $incdir .= "+incdir+../tb/${tbname}_test/sv \\\n";
6200
    $incdir .= "+incdir+../tb/${tbname}_tb/sv \\\n";
6201
 
6202
    print FH "$incdir";
6203
    print FH "-F ../${dut_tb_dir}/files.f \\\n";
6204
 
6205
    if ($common_pkg_fname) {
6206
        open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f";
6207
        print FH "../${dut_tb_dir}/${common_pkg_fname} \\\n" unless (grep /$common_pkg_fname/,<FFH>);
6208
        close FFH;
6209
    }
6210
 
6211
    if ($common_env_pkg_fname) {
6212
        open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f";
6213
        print FH "../tb/include/${common_env_pkg_fname} \\\n" unless (grep /$common_env_pkg_fname/,<FFH>);
6214
        close FFH;
6215
    }
6216
 
6217
    #compile the register model package;
6218
    print FH "../tb/regmodel/${regmodel_file} \\\n" if $regmodel;
6219
 
6220
    #need to compile agents before envs
6221
    foreach my $aname (@stand_alone_agents) {
6222
        if ( $aname ne "" ) {
6223
            print FH "../tb/${aname}/sv/${aname}_pkg.sv \\\n";
6224
            print FH "../tb/${aname}/sv/${aname}_if.sv \\\n";
6225
        }
6226
    }
6227
    foreach my $agent (@agent_list) {
6228
        if ( !grep( /$agent/, @stand_alone_agents ) ) {
6229
            print FH "../tb/${agent}/sv/${agent}_pkg.sv \\\n";
6230
            print FH "../tb/${agent}/sv/${agent}_if.sv \\\n";
6231
        }
6232
    }
6233
 
6234
    if ( $split_transactors eq "YES") {
6235
       foreach my $agent (@agent_list) {
6236
            print FH "../tb/${agent}/sv/${agent}_bfm.sv \\\n";
6237
       }
6238
    }
6239
 
6240
    if ( defined $syosil_scoreboard_src_path ) {
6241
        print FH "../../$syosil_scoreboard_src_path/pk_syoscb.sv \\\n";
6242
    }
6243
 
6244
    print FH "../tb/${tbname}/sv/${tbname}_pkg.sv \\\n";
6245
    print FH "../tb/${tbname}_test/sv/${tbname}_test_pkg.sv \\\n";
6246
    print FH "../tb/${tbname}_tb/sv/${tbname}_th.sv \\\n";
6247
    print FH "../tb/${tbname}_tb/sv/${tbname}_tb.sv \\\n";
6248
}
6249
 
6250
sub print_structure {
6251
    print "Generated hierarchy of envs and agents:\n";
6252
    foreach my $agent_env (@env_list) {
6253
        print "  m_$agent_env\n";
6254
 
6255
        $agent_env =~ /(\w+)_env/;
6256
        my $agent_name = $1;
6257
 
6258
        for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) {
6259
            my $suffix = calc_suffix($i, $number_of_instances{$agent_name});
6260
 
6261
            print "    m_${agent_name}${suffix}_agent\n";
6262
        }
6263
        foreach my $extra_agent ( @{ $env_agents{$agent_env} } ) {
6264
            print "    m_${extra_agent}_agent\n";
6265
        }
6266
    }
6267
    foreach my $agent (@top_env_agents) {
6268
        for ( my $i = 0 ; $i < $number_of_instances{$agent} ; $i++ ) {
6269
            my $suffix = calc_suffix($i, $number_of_instances{$agent});
6270
 
6271
            print "  m_${agent}${suffix}_agent\n";
6272
        }
6273
    }
6274
 
6275
    #print "----- ----- ----- ----- -----\n";
6276
    #foreach my $inst ( @agent_instance_names ) {
6277
    #    print "Instance name = $inst, agent type = $agent_type_by_inst{$inst}\n";
6278
    #}
6279
    #print "----- ----- ----- ----- -----\n";
6280
 
6281
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.