URL
https://opencores.org/ocsvn/lpffir/lpffir/trunk
Subversion Repositories lpffir
[/] [lpffir/] [trunk/] [uvm/] [tools/] [easier_uvm_gen/] [easier_uvm_gen.pl] - Rev 10
Go to most recent revision | Compare with Previous | Blame | View Log
#!/usr/bin/perl ## ##---------------------------------------------------------------------- ## Copyright (c) 2013-2016 by Doulos Ltd. ## ## Licensed under the Apache License, Version 2.0 (the "License"); ## you may not use this file except in compliance with the License. ## You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, software ## distributed under the License is distributed on an "AS IS" BASIS, ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ## See the License for the specific language governing permissions and ## limitations under the License. ## ---------------------------------------------------------------------- ## Based on the juvb11.pl script v1.09 by Jim McGrath, Cadence which was uploaded as UVMWorld contribution on 16 September 2011 ## 19/02/2014 Author Christoph Suehnel, Doulos ## 24/02/2014 David Long, Doulos - DUT port list, auto instantiation in top ## 12/03/2014 David Long, Doulos - Support for multiple IFs/register sub-blocks ## 04/04/2014 David Long, Doulos - Naming conventions and use of config_db updated ## 11/04/2014 David Long, Doulos - Constraints added to seq_item ## 20/05/2014 David Long, Doulos - Support for multiple agents within envs. Simplified directory structure, ## 05/06/2014 David Long, Doulos - Revised template file format and options. Preliminary version for public release ## 01/09/2014 David Long, Doulos - DUT now in test harness module. Removed unnecessary child environments. Improvements to code formatting ## 21/09/2014 David Long, Doulos - trans_var allows typedef. item replaced by req. Added checks/coverage_enable. ## 08/10/2014 David Long, Doulos - fixed some naming conventions. Check "is_active" ## 13/10/2014 David Long, Doulos - fixed bug with "uvm_seqr_class" switch in template file ## 13/10/2014 David Long, Doulos - default_sequence class now derived directly from uvm_sequence ## 17/10/2014 David Long, Doulos - removed unnecessary base class for test. Configuration for top env now set in TB module ## 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. ## Added checking for critical warnings re include files (can be ignored by adding -c ("continue") flag to command line ## 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) ## 05/11/2014 David Long, Doulos - Generated packages now include files directly (removed .svh files). Removed unused *_common.sv files ## 07/11/2014 David Long, Doulos - Removed <test>_common_pkg include file - these items are now written to test common package directly. ## Test common package file is not regenerated if it has been modified since it was created (i.e. user changes are preserved). ## 07/11/2014 David Long, Doulos - Top-level sequence uses UVM 1.2 API to raise/drop objections in pre/post-start. ## 17/11/2014 David Long, Doulos - Corrected minor formatting issues. ## 16/12/2014 John Aynsley, Doulos - Tidied up positioning of blank lines. ## 19/12/2014 John Aynsley, Doulos - Add m_ prefix to member variables. Add some pretty-printing ## 05/01/2015 John Aynsley, Doulos - Fix bug with properties leaking between agents ## 16/01/2015 John Aynsley, Doulos - Tweak formatting ## 20/01/2015 John Aynsley, Doulos - Tweak formatting ## 28/01/2015 John Aynsley, Doulos - Add a parameter regmodel_file to reg.tpl to replace the hardwired "regmodel.sv" ## 28/01/2015 John Aynsley, Doulos - Allow regmodel_ as well as rm_ in reg.tpl file ## 29/01/2015 John Aynsley, Doulos - Call `uvm_error if randomize fails ## 04/02/2015 John Aynsley, Doulos - Fix bug so that common package gets included in agent interfaces, rationalize package imports ## 04/02/2015 John Aynsley, Doulos - Allow named constraints as trans_var = values ## 19/02/2015 John Aynsley, Doulos - Label coverpoints using field name rather than number ## 19/02/2015 John Aynsley, Doulos - Add new include files inside/after classes ## 07/04/2015 John Aynsley, Doulos - Add new include file inside th module ## 21/04/2015 John Aynsley, Doulos - Generate get/set_starting_phase methods for all sequences ## 05/05/2015 John Aynsley, Doulos - Add several new include files and independent flags to suppress the generation of default members and methods ## 06/05/2015 John Aynsley, Doulos - Add ability to inline all user-defined include files ## 11/05/2015 John Aynsley, Doulos - Restructure <top>_common_pkg as per common_pkg (not backward-compatible) ## 12/05/2015 John Aynsley, Doulos - Add _prepend_to_ and _append_to_ include files for build_phase, connect_phase, run_phase methods ## 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) ## 12/05/2015 John Aynsley, Doulos - Don't generate empty run_phase for test (allows it to be user-defined more conveniently) ## 19/05/2015 John Aynsley, Doulos - Support multiple instances of each interface (with _N suffix in pinlist file) ## 20/05/2015 John Aynsley, Doulos - Refactor all the pretty-print code ## 26/05/2015 John Aynsley, Doulos - Generate comments showing possible include locations ## 30/05/2015 John Aynsley, Doulos - Permit trans_item name clashes across agents by distinguishing the filenames ## 05/06/2015 John Aynsley, Doulos - Add agent_copy_config_vars ## 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) ## 16/06/2015 John Aynsley, Doulos - Add prefix = setting to common template file as alternative to -p switch ## 17/06/2015 John Aynsley, Doulos - Refactor by adding warning_prompt ## 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 ## 20/06/2015 John Aynsley, Doulos - Make reg.tpl optional ## 21/06/2015 John Aynsley, Doulos - Add top_env_generate_end_of_elaboration (default yes) ## 21/06/2015 John Aynsley, Doulos - Revamp messages printed from script ## 21/06/2015 John Aynsley, Doulos - Fix bug in gen_env which was repeating additional agent declaration in number_of_instances loop ## 21/06/2015 John Aynsley, Doulos - Add compile/run script for Riviera ## 30/09/2015 John Aynsley, Doulos - Add command line flag -x to output dut_source_path, inc_path, and project without generating any code ## 01/10/2015 John Aynsley, Doulos - Adjust compile_vcs.do and compile_ius.do scripts to use built-in versions of UVM-1.2 ## 01/10/2015 John Aynsley, Doulos - Replace factory with uvm_factory::get(). ## 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 ## 20/10/2015 John Aynsley, Doulos - Extend command line flag -x to output regmodel_file without generating any code ## 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) ## 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 ## 23/10/2015 John Aynsley, Doulos - Add common template setting uvm_cmdline = , and remove +UVM_VERBOSITY=FULL from sim scripts, using $uvm_cmdline instead ## 26/10/2015 John Aynsley, Doulos - With -x regmodel_file, force the script to read reg.tpl if the file exists ## 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 ## 09/11/2015 John Aynsley, Doulos - Call comparer.compare_field in overridden do_compare method of uvm_sequence_item (to keep Syosil scoreboard happy) ## 16/11/2015 John Aynsley, Doulos - Add top_default_seq_count in common template ## 17/11/2015 John Aynsley, Doulos - Rewrite the pretty-printing code ## 17/11/2015 John Aynsley, Doulos - Add support for the Syosil Versatile Scoreboard: syosil_scoreboard_src_path, ref_model_input, ref_model_output ## ref_model_compare_method, ref_model_inc_before/inside/after_class ## 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 ## 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! ## 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 ## 26/11/2015 John Aynsley, Doulos - Add trans_enum_meta for metadata that happens to be of enum type ## 27/11/2015 John Aynsley, Doulos - Allow single unpacked array dimension in trans_var declaration ## 17/12/2015 John Aynsley, Doulos - Minor cosmetic surgery on the source code ## 18/12/2015 John Aynsley, Doulos - Eliminated the <agent>_env directory and the <agent>_env_pkg. There is now only an <agent>_pkg. ## Now only 1 pkg per UVC. Also scrapped subs gen_regmodel_pkg and gen_regmodel_env ## 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 ## 19/12/2015 John Aynsley, Doulos - Use coverage_enable to condition the calling of sample(), not the instantiation of a subscriber for an agent ## 19/12/2015 John Aynsley, Doulos - Move code executed after parsing control files to separate subs ## 20/12/2015 John Aynsley, Doulos - Removed the unused dut_inc_path and inc_file code ## 23/12/2015 John Aynsley, Doulos - Permit / in include filenames so that ./include can be structured into subdirectories ## 11/01/2016 John Aynsley, Doulos - Permit trans_var/trans_meta = // SystemVerilog comment ## 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 ## 21/01/2016 John Aynsley, Doulos - Add dual_top and split_transactors to support acceleration/emulation-ready environments ## 01/02/2016 John Aynsley, Doulos - Add timeunit and timeprecision to interfaces (was previously only inserted in modules) ## 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 ## 15/02/2016 John Aynsley, Doulos - Add top_env_generate_run_phase (default yes) ## 15/02/2016 John Aynsley, Doulos - Add generate_file_header and file_header_inc ## 15/02/2016 John Aynsley, Doulos - Clean up auto-generated file header to only write out lines that are defined ## 17/02/2016 John Aynsley, Doulos - Add adapter_generate_methods_inside/after_class and adapter_inc_before/inside/after class ## 18/02/2016 John Aynsley, Doulos - Add nested_config_objects ## 18/02/2016 John Aynsley, Doulos - Add top_env_config_append_to_new ## 18/02/2016 John Aynsley, Doulos - Add top_env_config_generate_methods_inside/after_class ## 18/02/2016 John Aynsley, Doulos - Add agent_config_generate_methods_inside/after_class ## 18/02/2016 John Aynsley, Doulos - Add tb_generate_run_test ## 08/03/2016 John Aynsley, Doulos - Add -s command line switch to override syosil_scoreboard_src_path setting in common template ## 31/03/2016 John Aynsley, Doulos - Permit end-of-line comment with DEC in pinlist file ## 31/03/2016 John Aynsley, Doulos - Fix bug with trailing comments after last port connection in pinlist file ## 31/03/2016 John Aynsley, Doulos - Add calls to .set_item_context() before randomizing sequence objects to ensure random stability ## 05/04/2016 John Aynsley, Doulos - Replace -f with -F in Riviera script ## 06/04/2016 John Aynsley, Doulos - Modify compile_riviera.do script to compile everything UVM with a single call to alog ## 15/04/2016 John Aynsley, Doulos - Add tb_prepend_to_initial and tb_inc_before_run_test ## 15/04/2016 John Aynsley, Doulos - Add generate_interface_instance = no (interface instance not generated and vif not assigned) ## 15/04/2016 John Aynsley, Doulos - Add byo_interface ## 15/04/2016 John Aynsley, Doulos - Allow user-defined interface instance names in the pinlist file ## 15/04/2016 John Aynsley, Doulos - Changed "virtual interface is not set!" report from FATAL to WARNING - because might have a parameterized interface ## 12/05/2016 John Aynsley, Doulos - Allow multiple +uvm_cmdline settings to apply additively ## 27/05/2016 John Aynsley, Doulos - Don't generate empty build_phase method for monitor ## 27/05/2016 John Aynsley, Doulos - Modify compile_riviera.do script to use the UVM 1.2 library supplied with Riviera ## 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 ## 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. ## 07/10/2016 John Aynsley, Doulos - Move assignment to m_item in function <agent>_coverage::write ## 07/10/2016 John Aynsley, Doulos - Move lines around in generated code for top_default_sequence ## 07/10/2016 John Aynsley, Doulos - Add an m_config member to every ${agent_name}_env_default_seq register sequence and assign before start ## 10/10/2016 John Aynsley, Doulos - Add an m_config member to every ${agent_name}_default_seq and assign before start ## 10/10/2016 John Aynsley, Doulos - Add an m_config member to every driver and monitor and assign in agent::connect ## Easier UVM Generator use strict; use warnings; require 5.8.0; use File::Copy::Recursive qw(dircopy); use File::Copy "cp"; use File::stat; my $VERNUM = "2017-01-19"; # Subroutine prototypes: sub parse_cmdline; sub usage; sub parse_common; sub after_parse_common; sub parse_reg_template; sub parse_template; sub after_parse_template; sub check_file; sub check_inc_file; sub check_common_pkg; sub check_common_env_pkg; sub gen_bfm; sub gen_if; sub gen_seq_item; sub gen_driver; sub gen_monitor; sub gen_sequencer; sub gen_config; sub gen_cov; sub gen_agent; sub gen_env; sub gen_seq_lib; sub gen_env_seq_lib; sub gen_agent_pkg; sub gen_top_pkg; sub gen_dut_inst; sub gen_top; sub gen_port_converter; sub gen_ref_model; sub gen_top_env; sub gen_top_config; sub gen_top_seq_lib; sub gen_top_test; sub gen_regmodel_adapter; sub gen_regmodel_coverage; sub gen_regmodel_seq_lib; sub gen_questa_script; sub gen_vcs_script; sub gen_ius_script; sub gen_riviera_script; sub gen_compile_file_list; sub get_pkg_name; sub write_file_header; # Scalar Variables: my $agent_has_env; my $agent_if; my $agent_item; my $agent_name; my $agent_reset; my $agent_seqr_class; my $aname; my $argnum; my $author; my $backup; my $common_pkg; my $common_pkg_fname; my $common_env_pkg; my $common_env_pkg_fname; my $common_tpl_fname; my $company; my $continue_on_warning; my $copyright; my $date; my $dept; my $dir1; my $dir2; my $dir; my $dual_top; my $dut_iname; my $dut_path; my $dut_pfile; my $dut_tb_dir; my $dut_tb_path; my $dut_top; my $ele; my $email; my $env_clock_list; my $env_reset_list; my $field; my $file_header_inc; my $flag_dut_source_path; my $flag_inc_path; my $flag_project; my $flag_regmodel_file; my $flag_x; my $flag_nopack; my $comments_at_include_locations; my $generate_file_header; my $nested_config_objects; my $i; my $inc_file; my $inc_path; my $incdir; my $name; my $pf; my $port_decl; my $project; my $reg_template; my $regmodel; my $regmodel_file; my $split_transactors; my $syosil_scoreboard_src_path; my $top_reg_block_type; my $tbname; my $tb_inc_before_run_test; my $tb_inc_before_run_test_inline; my $tb_inc_inside_module; my $tb_inc_inside_inline; my $tb_generate_run_test; my $tb_module_name; my $tb_prepend_to_initial; my $tb_prepend_to_initial_inline; my $th_module_name; my $tel; my $template_list; my $template_name; my $th_generate_clock_and_reset; my $th_inc_inside_module; my $th_inc_inside_inline; my $timeunit; my $timeprecision; my $test_generate_methods_inside_class; my $test_generate_methods_after_class; my $test_inc_before_class; my $test_inc_before_inline; my $test_inc_inside_class; my $test_inc_inside_inline; my $test_inc_after_class; my $test_inc_after_inline; my $test_prepend_to_build_phase; my $test_prepend_to_build_phase_inline; my $test_append_to_build_phase; my $test_append_to_build_phase_inline; my $top_env_config_append_to_new; my $top_env_config_append_to_new_inline; my $top_env_config_generate_methods_inside_class; my $top_env_config_generate_methods_after_class; my $top_default_seq_count; my $top_env_config_inc_before_class; my $top_env_config_inc_before_inline; my $top_env_config_inc_inside_class; my $top_env_config_inc_inside_inline; my $top_env_config_inc_after_class; my $top_env_config_inc_after_inline; my $top_env_generate_methods_inside_class; my $top_env_generate_methods_after_class; my $top_env_generate_end_of_elaboration; my $top_env_generate_run_phase; my $top_env_inc_before_class; my $top_env_inc_before_inline; my $top_env_inc_inside_class; my $top_env_inc_inside_inline; my $top_env_inc_after_class; my $top_env_inc_after_inline; my $top_env_prepend_to_build_phase; my $top_env_prepend_to_build_phase_inline; my $top_env_append_to_build_phase; my $top_env_append_to_build_phase_inline; my $top_env_append_to_connect_phase; my $top_env_append_to_connect_phase_inline; my $top_env_append_to_run_phase; my $top_env_append_to_run_phase_inline; my $top_seq_inc; my $top_seq_inc_inline; my $uvm_cmdline; my $uvm_reg_addr; my $uvm_reg_data; my $uvm_reg_kind; my $var_decl; my $year; my $version; # Hash Variables my %agent_adapter_generate_methods_inside_class; my %agent_adapter_generate_methods_after_class; my %agent_adapter_inc_before_class; my %agent_adapter_inc_before_inline; my %agent_adapter_inc_inside_class; my %agent_adapter_inc_inside_inline; my %agent_adapter_inc_after_class; my %agent_adapter_inc_after_inline; my %agent_append_to_build_phase; my %agent_append_to_build_phase_inline; my %agent_append_to_connect_phase; my %agent_append_to_connect_phase_inline; my %agent_checks_enable; my %agent_config_generate_methods_inside_class; my %agent_config_generate_methods_after_class; my %agent_config_inc_before_class; my %agent_config_inc_before_inline; my %agent_config_inc_inside_class; my %agent_config_inc_inside_inline; my %agent_config_inc_after_class; my %agent_config_inc_after_inline; my %agent_copy_config_vars; my %agent_copy_config_vars_inline; my %agent_cover_generate_methods_inside_class; my %agent_cover_generate_methods_after_class; my %agent_cover_inc; my %agent_cover_inc_inline; my %agent_cover_inc_before_class; my %agent_cover_inc_before_inline; my %agent_cover_inc_inside_class; my %agent_cover_inc_inside_inline; my %agent_cover_inc_after_class; my %agent_cover_inc_after_inline; my %agent_coverage_enable; my %agent_driv_inc; my %agent_driv_inc_inline; my %agent_driv_inc_before_class; my %agent_driv_inc_before_inline; my %agent_driv_inc_inside_class; my %agent_driv_inc_inside_inline; my %agent_driv_inc_after_class; my %agent_driv_inc_after_inline; my %agent_env_prepend_to_build_phase; my %agent_env_prepend_to_build_phase_inline; my %agent_env_append_to_build_phase; my %agent_env_append_to_build_phase_inline; my %agent_env_append_to_connect_phase; my %agent_env_append_to_connect_phase_inline; my %agent_env_generate_methods_inside_class; my %agent_env_generate_methods_after_class; my %agent_env_inc_before_class; my %agent_env_inc_before_inline; my %agent_env_inc_inside_class; my %agent_env_inc_inside_inline; my %agent_env_inc_after_class; my %agent_env_inc_after_inline; my %agent_env_seq_inc; my %agent_env_seq_inc_inline; my %agent_factory_set; my %agent_generate_methods_inside_class; my %agent_generate_methods_after_class; my %agent_is_active; my %agent_inc_before_class; my %agent_inc_before_inline; my %agent_inc_inside_class; my %agent_inc_inside_inline; my %agent_inc_after_class; my %agent_inc_after_inline; my %agent_inc_inside_bfm; my %agent_inc_inside_bfm_inline; my %agent_mon_inc; my %agent_mon_inc_inline; my %agent_mon_inc_before_class; my %agent_mon_inc_before_inline; my %agent_mon_inc_inside_class; my %agent_mon_inc_inside_inline; my %agent_mon_inc_after_class; my %agent_mon_inc_after_inline; my %agent_parent; my %agent_prepend_to_build_phase; my %agent_prepend_to_build_phase_inline; my %agent_seq_inc; my %agent_seq_inc_inline; my %agent_seqr_inc_before_class; my %agent_seqr_inc_before_inline; my %agent_seqr_inc_inside_class; my %agent_seqr_inc_inside_inline; my %agent_seqr_inc_after_class; my %agent_seqr_inc_after_inline; my %agent_item_types; my %agent_trans_generate_methods_inside_class; my %agent_trans_generate_methods_after_class; my %agent_trans_inc_before_class; my %agent_trans_inc_before_inline; my %agent_trans_inc_inside_class; my %agent_trans_inc_inside_inline; my %agent_trans_inc_after_class; my %agent_trans_inc_after_inline; my %agent_type_by_inst; my %bus2reg_map; my %byo_interface; my %enum_var_types; my %env_agents; my %generate_interface_instance; my %if_inc_inside_interface; my %if_inc_inside_inline; my %if_instance_names; # Used to identify instances in the dut_pfile (the pinlist) my %number_of_instances; # Number of instances required of each agent/interface my %reg_access_block_type; # Type of uvm_reg_block class containing registers 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 my %reg_access_map; # Instance of map within uvm_reg_block my %reg_access_mode; # Register access mode WR WO RO my %reg_cover_generate_methods_inside_class; my %reg_cover_generate_methods_after_class; my %reg_cover_inc; my %reg_cover_inc_inline; my %reg_cover_inc_before_class; my %reg_cover_inc_before_inline; my %reg_cover_inc_inside_class; my %reg_cover_inc_inside_inline; my %reg_cover_inc_after_class; my %reg_cover_inc_after_inline; my %ref_model; my %ref_model_inputs; my %ref_model_outputs; my %ref_model_compare_method; my %ref_model_inc_before_class; my %ref_model_inc_before_inline; my %ref_model_inc_inside_class; my %ref_model_inc_inside_inline; my %ref_model_inc_after_class; my %ref_model_inc_after_inline; my %top_factory_set; my %tpl_fname; my %unpacked_bound; # Array Variables my @additional_agents; my @agent_clock_array; my @agent_instance_names; my @agent_list; # Array of all agent names my @agent_port_array; my @agent_reset_array; my @agent_var_array; my @agent_enum_array; my @agent_meta_array; my @agent_var_cnstr_array; my @all_agent_ifs; # Array of all interface names, including the _if suffix (not the interface instance names) my @clist; my @common_config_var_array; my @config_var_array; my @elist; my @env_list; my @fields; my @inc_path_list; my @list; my @all_tx_vars; my @non_local_tx_vars; my @non_meta_tx_vars; my @non_reg_env; my @reg_env; my @rlist; my @stand_alone_agents; my @top_env_agents; open( LOGFILE, ">easier_uvm_gen.log" ); print LOGFILE "\nEasier UVM Code Generator version ${VERNUM}" . " (Send feedback to info\@doulos.com)\n"; set_default_values(); parse_cmdline(); parse_common(); after_parse_common(); deal_with_deprecated_reg_template(); handle_minus_x_flag(); #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 print "Easier UVM Code Generator version ${VERNUM}\n"; check_common_pkg($common_pkg_fname) if $common_pkg_fname; check_common_env_pkg($common_env_pkg_fname) if $common_env_pkg_fname; create_directories_and_copy_files(); # Process the agent templates (@list created by parse_cmdline) print LOGFILE "\nParsing Templates ...\n\n"; foreach my $i ( 0 .. @list - 1) { if ( $list[$i] ne "" ) { $template_name = $list[$i]; printf LOGFILE "Reading[$i]: $list[$i]\n"; parse_template(); after_parse_template(); # Make the per-agent directories $dir = "${project}/tb/${agent_name}"; printf LOGFILE "dir: $dir\n"; mkdir( $dir, 0755 ); mkdir( $dir . "/sv", 0755 ); print LOGFILE "Writing code to files\n"; # Create the agent files gen_if(); if ( $split_transactors eq "YES") { gen_bfm(); } gen_seq_item(); gen_config(); gen_driver(); gen_monitor(); gen_sequencer(); gen_cov(); gen_agent(); gen_seq_lib(); # Do not generate env or env_seq_lib if regmodel used or $agent_has_env = no do { gen_env(); gen_env_seq_lib(); } unless ( exists $reg_access_mode{$agent_name} ) or $agent_has_env eq "NO"; gen_agent_pkg(); } } if ( $regmodel eq 1 ) { gen_regmodel_pkg(); foreach my $agent ( keys(%reg_access_mode) ) { $agent_name = $agent; gen_env(); gen_regmodel_adapter(); gen_regmodel_coverage(); gen_regmodel_seq_lib(); } } extra_checking_for_additional_agents(); print LOGFILE "top env agents = @top_env_agents\n"; print LOGFILE "Generating testbench in ${project}/tb\n"; print "Generating testbench in ${project}/tb\n"; gen_top_config(); gen_port_converter(); foreach my $ref_model_name ( keys(%ref_model) ) { gen_ref_model($ref_model_name); } gen_top_env(); gen_top_seq_lib(); gen_top_pkg(); gen_top_test(); gen_top(); print "Generating simulator scripts in ${project}/sim\n"; print LOGFILE "Generating simulator scripts in ${project}/sim\n"; deal_with_files_f(); gen_questa_script(); gen_vcs_script(); gen_ius_script(); gen_riviera_script(); print_structure(); print LOGFILE "Code Generation complete\n"; # ---------- Subroutines ------------------------------------------------- sub set_default_values { $date = localtime; $project = "generated_tb"; $backup = "yes"; $version = "1.0"; $inc_path = "include"; $inc_file = ""; $dut_path = "dut"; $common_pkg = ""; $common_pkg_fname = ""; $common_env_pkg = ""; $common_env_pkg_fname = ""; $common_tpl_fname = "common.tpl"; $agent_name = ""; $agent_if = ""; $agent_item = ""; $dut_iname = "uut"; #instance name of dut in tb $timeunit = "1ns"; $timeprecision = "1ps"; $regmodel = 0; $dut_top = ""; #top level dut module $dut_pfile = "pinlist"; #dut port list file $uvm_cmdline = ""; $top_default_seq_count = undef; $env_reset_list = ""; $env_clock_list = ""; $tbname = undef; $regmodel_file = "regmodel.sv"; $top_reg_block_type = undef; $syosil_scoreboard_src_path = undef; $template_name = "example.tpl"; #default template name $template_list = ""; #default template list $reg_template = undef; $dual_top = "NO"; $split_transactors = "NO"; } sub parse_cmdline { print LOGFILE "\nParsing cmdline ...\n\n"; print LOGFILE "num args is " . $#ARGV . "\n"; if ( $#ARGV == -1 ) { usage(); } ### no arguments, print help and exit ###if ($ARGV[$argnum] =~ m/\s*help/i) if ( $ARGV[0] =~ m/\s*(-help|-hel|-he|-h)/i ) { usage(); } my $pnum_c = -2; my $pnum_r = -2; my $pnum_p = -2; my $pnum_m = -2; my $pnum_s = -2; my $pnum_n = -2; $continue_on_warning = 0; # Searching for -x dut_source_path, -x inc_path, and -x project flag foreach $argnum ( 0 .. $#ARGV) { if ( $ARGV[$argnum] =~ m/\s*(-x)/i ) { if ( $ARGV[ $argnum + 1 ] eq "dut_source_path" ) { $flag_x = 1; $flag_dut_source_path = 1; } if ( $ARGV[ $argnum + 1 ] eq "inc_path" ) { $flag_x = 1; $flag_inc_path = 1; } if ( $ARGV[ $argnum + 1 ] eq "project" ) { $flag_x = 1; $flag_project = 1; } if ( $ARGV[ $argnum + 1 ] eq "regmodel_file" ) { $flag_x = 1; $flag_regmodel_file = 1; } } } # Searching for "continue on critical warnings" flag foreach $argnum ( 0 .. $#ARGV) { if ( $ARGV[$argnum] =~ m/\s*(-c)/i ) { $pnum_c = $argnum; $continue_on_warning = 1; printf LOGFILE "Code generation will continue if critical warnings are issued\n"; printf LOGFILE "pnum_c: $pnum_c\n"; } } # Searching for register flag printf LOGFILE "Searching for regmodel flag\n"; foreach $argnum ( 0 .. $#ARGV) { if ( $ARGV[$argnum] =~ m/\s*(-r)/i ) { $regmodel = 1; $pnum_r = $argnum; printf LOGFILE "regmodel: $regmodel, Register layer will be included\n"; printf LOGFILE "pnum_r: $pnum_r\n"; } } # Searching for project name printf LOGFILE "Searching for prefix\n"; foreach $argnum ( 0 .. $#ARGV) { if ( $ARGV[$argnum] =~ m/\s*(-p)/i ) { $tbname = $ARGV[ $argnum + 1 ]; $pnum_p = $argnum; printf LOGFILE "prefix: $tbname\n"; printf LOGFILE "pnum_p: $pnum_p\n"; } } # Searching for common template filename printf LOGFILE "Searching for common template\n"; foreach $argnum ( 0 .. $#ARGV) { if ( $ARGV[$argnum] =~ m/\s*(-m)/i ) { $common_tpl_fname = $ARGV[ $argnum + 1 ]; $pnum_m = $argnum; printf LOGFILE "common_tpl_fname: $common_tpl_fname\n"; printf LOGFILE "pnum_m: $pnum_m\n"; } } # Searching for Syosil scoreboard path printf LOGFILE "Searching for Syosil scoreboard path\n"; foreach $argnum ( 0 .. $#ARGV) { if ( $ARGV[$argnum] =~ m/\s*(-s)/i ) { $syosil_scoreboard_src_path = $ARGV[ $argnum + 1 ]; $pnum_s = $argnum; printf LOGFILE "syosil_scoreboard_src_path: $syosil_scoreboard_src_path\n"; printf LOGFILE "pnum_s: $pnum_s\n"; } } # Searching for -nopack flag foreach $argnum ( 0 .. $#ARGV) { if ( $ARGV[$argnum] =~ m/\s*(-nopack)/i ) { $flag_nopack = 1; $pnum_n = $argnum; } } # searching for template (agent) names printf LOGFILE "Searching for templates\n"; foreach $argnum ( 0 .. $#ARGV) { if ( $argnum != $pnum_c && $argnum != $pnum_r && $argnum != $pnum_p && $argnum != $pnum_p + 1 && $argnum != $pnum_m && $argnum != $pnum_m + 1 && $argnum != $pnum_s && $argnum != $pnum_s + 1 && $argnum != $pnum_n ) { #check for template name if ( $ARGV[$argnum] =~ m/\s*(-template|-templat|-templa|-templ|-tem|-te|-t)/i ) { print LOGFILE "template: $ARGV[$argnum]\n"; } else { if ( $ARGV[$argnum] ne "reg.tpl" ) { $template_list = "$template_list $ARGV[$argnum]"; #print LOGFILE "T_List: $template_list\n"; } else { $reg_template = $ARGV[$argnum]; } } print LOGFILE "T_List: $template_list\n"; if ( $ARGV[$argnum] =~ m/\s*(-help|-hel|-he|-h)/i ) { usage(); } } @list = split /\s+/, $template_list; foreach $i ( 0 .. @list-1 ) { if ( $list[$i] ne "" ) { printf LOGFILE "List: $list[$i]\n"; } } } @list or die "ERROR! You must specify at least 1 template file)\n"; } sub usage { print "\n"; print "USAGE: perl easier_uvm_gen.pl [-t] <filename> <filename> ... list of template file names\n"; print "\n"; print " -p <top> Prefix used to construct names associated with top-level env, default is top\n"; print " -m <filename> Path to common template file, default is common.tpl\n"; print " -s <path> Path to source files for Syosil scoreboard (overrides syosil_scoreboard_src_path in common template)\n"; print " -c The code generator will continue after warnings\n"; print " -r Causes a register model to be instantiated in the generated code (switch is no longer necessary}\n"; print " -x dut_source_path Returns the value of the dut_source_path setting\n"; print " -x inc_path Returns the value of the inc_path setting\n"; print " -x project Returns the value of the project setting\n"; print " -x regmodel_file Returns the value of the regmodel_file setting\n"; print " -nopack Suppresses generation of do_pack & do_unpack methods for backward compatibility\n"; print "\n"; exit; } # end sub usage sub parse_common { my $template_name = $common_tpl_fname; @common_config_var_array = (); open( TH, $template_name ) || die "Exiting due to Error: can't open template: ${template_name}\n"; print LOGFILE "Parsing common : $template_name ...\n\n"; for ( ; ; ) { my $line; undef $!; unless ( defined( $line = <TH> ) ) { die $! if $!; last; # reached EOF } next if ( $line =~ m/^\s*#/ ); #comment line starts with "#" next if ( $line =~ m/^\s+$/ ); #blank line $line =~ s/(^.*?)#.*/$1/; #delete trailing comments $line =~ /^\s*(\w+)\s*=\s*(.+?)\s*$/ or die "Exiting due to Error: bad entry in line $. of ${common_tpl_fname}: $line\n"; my $param_name = $1; my $param_value = $2; #check for dut path if ( $param_name =~ /dut_source_path/i ) { $dut_path = $param_value; print LOGFILE "dut_path: $dut_path\n"; } #check for include paths if ( $param_name =~ /^\s*inc_path/i ) { $inc_path = $param_value; } #check for project if ( $param_name =~ /project/i ) { $project = $param_value; print LOGFILE "Project: $project\n"; } #check for regmodel file if ( $param_name =~ /regmodel_file/i) { unless (defined($flag_x)) { check_file($param_value); } $regmodel_file = $param_value; print LOGFILE "regmodel_file: $regmodel_file\n"; } #check for top-level regmodel type if ( $param_name =~ /top_reg_block_type/i) { $top_reg_block_type = $param_value; print LOGFILE "top_reg_block_type: $top_reg_block_type\n"; } # Don't parse the rest of the settings if called with the -x switch unless (defined($flag_x)) { if ( $param_name =~ /prefix/i ) { unless ( defined $tbname ) { $tbname = $param_value; print LOGFILE "Prefix: $tbname\n"; } } if ( $param_name =~ /backup/i ) { $backup = uc $param_value; print LOGFILE "Backup: $backup\n"; } if ( $param_name =~ /comments_at_include_locations/i ) { $comments_at_include_locations = uc $param_value; print LOGFILE "comments_at_include_locations = $comments_at_include_locations\n"; } if ( $param_name =~ /copyright/i ) { $copyright = $param_value; print LOGFILE "$copyright\n"; } if ( $param_name =~ /^\s*name/i ) { $author = $param_value; print LOGFILE "Name: $author\n"; } if ( $param_name =~ /email/i ) { $email = $param_value; print LOGFILE "email: $email\n"; } if ( $param_name =~ /tel/i ) { $tel = $param_value; print LOGFILE "Tel: $tel\n"; } if ( $param_name =~ /dept/i ) { $dept = $param_value; print LOGFILE "dept: $dept\n"; } if ( $param_name =~ /company/i ) { $company = $param_value; print LOGFILE "company: $dept\n"; } if ( $param_name =~ /year/i ) { $year = $param_value; print LOGFILE "year: $year\n"; } if ( $param_name =~ /version/i ) { $version = $param_value; print LOGFILE "version : $version\n"; } if ( $param_name =~ /dut_top/i ) { $dut_top = $param_value; print LOGFILE "dut_top: $dut_top\n"; } if ( $param_name =~ /dut_iname/i ) { $dut_iname = $param_value; print LOGFILE "dut instance name: $dut_iname\n"; } if ( $param_name =~ /dut_pfile/i ) { $dut_pfile = $param_value; print LOGFILE "dut_pfile: $dut_pfile\n"; } if ( $param_name =~ /timeunit/i ) { $timeunit = $param_value; print LOGFILE "timeunit: $timeunit\n"; } if ( $param_name =~ /timeprecision/i ) { $timeprecision = $param_value; print LOGFILE "timeprecision: $timeprecision\n"; } if ( $param_name =~ /uvm_cmdline/i ) { $uvm_cmdline = $uvm_cmdline ? "$uvm_cmdline $param_value" : $param_value; print LOGFILE "uvm_cmdline: $uvm_cmdline\n"; } if ( $param_name =~ /nested_config_objects/i ) { $nested_config_objects = uc $param_value; print LOGFILE "nested_config_objects = $param_value\n"; } if ( $param_name =~ /common_pkg/i ) { $common_pkg_fname = $param_value; print LOGFILE "common package file name: $common_pkg_fname\n"; } if ( $param_name =~ /common_env_pkg/i ) { $common_env_pkg_fname = $param_value; print LOGFILE "common env package file name: $common_env_pkg_fname\n"; } if ( $param_name =~ /tb_inc_inside_module/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $tb_inc_inside_module = $1; $tb_inc_inside_inline = $3 if ($3); print LOGFILE "tb_inc_inside_module = $param_value\n"; } if ( $param_name =~ /tb_inc_before_run_test/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $tb_inc_before_run_test = $1; $tb_inc_before_run_test_inline = $3 if ($3); print LOGFILE "tb_inc_before_run_test = $param_value\n"; } if ( $param_name =~ /tb_prepend_to_initial/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $tb_prepend_to_initial = $1; $tb_prepend_to_initial_inline = $3 if ($3); print LOGFILE "tb_prepend_to_initial = $param_value\n"; } if ( $param_name =~ /tb_generate_run_test/i ) { $tb_generate_run_test = uc $param_value; print LOGFILE "tb_generate_run_test = $param_value\n"; } if ( $param_name =~ /th_generate_clock_and_reset/i ) { $th_generate_clock_and_reset = uc $param_value; print LOGFILE "th_generate_clock_and_reset = $param_value\n"; } if ( $param_name =~ /th_inc_inside_module/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $th_inc_inside_module = $1; $th_inc_inside_inline = $3 if ($3); print LOGFILE "th_inc_inside_module = $param_value\n"; } if ( $param_name =~ /generate_file_header/i ) { $generate_file_header = uc $param_value; print LOGFILE "generate_file_header = $param_value\n"; } if ( $param_name =~ /file_header_inc/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $file_header_inc = $1; print LOGFILE "file_header_inc = $param_value\n"; } if ( $param_name =~ /test_generate_methods_inside_class/i ) { $test_generate_methods_inside_class = uc $param_value; print LOGFILE "test_generate_methods_inside_class = $param_value\n"; } if ( $param_name =~ /test_generate_methods_after_class/i ) { $test_generate_methods_after_class = uc $param_value; print LOGFILE "test_generate_methods_after_class = $param_value\n"; } if ( $param_name =~ /test_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $test_inc_before_class = $1; $test_inc_before_inline = $3 if ($3); print LOGFILE "test_inc_before_class = $param_value\n"; } if ( $param_name =~ /test_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $test_inc_inside_class = $1; $test_inc_inside_inline = $3 if ($3); print LOGFILE "test_inc_inside_class = $param_value\n"; } if ( $param_name =~ /test_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $test_inc_after_class = $1; $test_inc_after_inline = $3 if ($3); print LOGFILE "test_inc_after_class = $param_value\n"; } if ( $param_name =~ /test_prepend_to_build_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $test_prepend_to_build_phase = $1; $test_prepend_to_build_phase_inline = $3 if ($3); print LOGFILE "test_prepend_to_build_phase = $param_value\n"; } if ( $param_name =~ /test_append_to_build_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $test_append_to_build_phase = $1; $test_append_to_build_phase_inline = $3 if ($3); print LOGFILE "test_append_to_build_phase = $param_value\n"; } if ( $param_name =~ /top_env_generate_methods_inside_class/i ) { $top_env_generate_methods_inside_class = uc $param_value; print LOGFILE "top_env_generate_methods_inside_class = $param_value\n"; } if ( $param_name =~ /top_env_generate_methods_after_class/i ) { $top_env_generate_methods_after_class = uc $param_value; print LOGFILE "top_env_generate_methods_after_class = $param_value\n"; } if ( $param_name =~ /top_env_generate_end_of_elaboration/i ) { $top_env_generate_end_of_elaboration = uc $param_value; print LOGFILE "top_env_generate_end_of_elaboration = $param_value\n"; } if ( $param_name =~ /top_env_generate_run_phase/i ) { $top_env_generate_run_phase = uc $param_value; print LOGFILE "top_env_generate_run_phase = $param_value\n"; } if ( $param_name =~ /top_env_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_env_inc_before_class = $1; $top_env_inc_before_inline = $3 if ($3); print LOGFILE "top_env_inc_before_class = $param_value\n"; } if ( $param_name =~ /top_env_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_env_inc_inside_class = $1; $top_env_inc_inside_inline = $3 if ($3); print LOGFILE "top_env_inc_inside_class = $param_value\n"; } if ( $param_name =~ /top_env_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_env_inc_after_class = $1; $top_env_inc_after_inline = $3 if ($3); print LOGFILE "top_env_inc_after_class = $param_value\n"; } if ( $param_name =~ /top_env_prepend_to_build_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_env_prepend_to_build_phase = $1; $top_env_prepend_to_build_phase_inline = $3 if ($3); print LOGFILE "top_env_prepend_to_build_phase = $param_value\n"; } if ( $param_name =~ /top_env_append_to_build_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_env_append_to_build_phase = $1; $top_env_append_to_build_phase_inline = $3 if ($3); print LOGFILE "top_env_append_to_build_phase = $param_value\n"; } if ( $param_name =~ /top_env_append_to_connect_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_env_append_to_connect_phase = $1; $top_env_append_to_connect_phase_inline = $3 if ($3); print LOGFILE "top_env_append_to_connect_phase = $param_value\n"; } if ( $param_name =~ /top_env_append_to_run_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_env_append_to_run_phase = $1; $top_env_append_to_run_phase_inline = $3 if ($3); print LOGFILE "top_env_append_to_run_phase = $param_value\n"; } if ( $param_name =~ /top_env_config_append_to_new/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_env_config_append_to_new = $1; $top_env_config_append_to_new_inline = $3 if ($3); print LOGFILE "top_env_config_append_to_new = $param_value\n"; } if ( $param_name =~ /top_env_config_generate_methods_inside_class/i ) { $top_env_config_generate_methods_inside_class = uc $param_value; print LOGFILE "top_env_config_generate_methods_inside_class = $param_value\n"; } if ( $param_name =~ /top_env_config_generate_methods_after_class/i ) { $top_env_config_generate_methods_after_class = uc $param_value; print LOGFILE "top_env_config_generate_methods_after_class = $param_value\n"; } if ( $param_name =~ /top_env_config_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_env_config_inc_before_class = $1; $top_env_config_inc_before_inline = $3 if ($3); print LOGFILE "top_env_config_inc_before_class = $param_value\n"; } if ( $param_name =~ /top_env_config_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_env_config_inc_inside_class = $1; $top_env_config_inc_inside_inline = $3 if ($3); print LOGFILE "top_env_config_inc_inside_class = $param_value\n"; } if ( $param_name =~ /top_env_config_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_env_config_inc_after_class = $1; $top_env_config_inc_after_inline = $3 if ($3); print LOGFILE "top_env_config_inc_after_class = $param_value\n"; } if ( $param_name =~ /top_seq_inc/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $top_seq_inc = $1; $top_seq_inc_inline = $3 if ($3); print LOGFILE "top_seq_inc = $param_value\n"; } if ( $param_name =~ /top_default_seq_count/i ) { $top_default_seq_count = $param_value; print LOGFILE "top_default_seq_count = $param_value\n"; } #check for top-level factory overrides if ( $param_name =~ /top_factory_set/i ) { $param_value =~ /\s*(\w+)(\s+|\s*,\s*)(\w+)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; $top_factory_set{$1} = $3; print LOGFILE "top_factory_set = $param_value\n"; } #check for config_var if ( $param_name =~ /config_var$/i ) { print LOGFILE "config_var: $param_value\n"; push @common_config_var_array, $param_value; } #Syosil scoreboard package source file if ( $param_name =~ /syosil_scoreboard_src_path/i ) { unless ( defined $syosil_scoreboard_src_path ) { check_file($param_value); $syosil_scoreboard_src_path = $param_value; print LOGFILE "syosil_scoreboard_src_path = $param_value\n"; } } #check for ref_model inputs if ( $param_name =~ /ref_model_input/i ) { $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; unless ( exists $ref_model{$1} ) { $ref_model{$1} = 1; } push @{ $ref_model_inputs{$1} }, $3; print LOGFILE "ref_model_input = $1 $3\n"; } #check for ref_model outputs if ( $param_name =~ /ref_model_output/i ) { $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; unless ( exists $ref_model{$1} ) { $ref_model{$1} = 1; } push @{ $ref_model_outputs{$1} }, $3; print LOGFILE "ref_model_output = $1 $3\n"; } #check for ref_model compare method if ( $param_name =~ /ref_model_compare_method/i ) { $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; unless ( exists $ref_model{$1} ) { $ref_model{$1} = 1; } $ref_model_compare_method{$1} = $3; print LOGFILE "ref_model_compare_method = $1 $3\n"; } #check for ref_model include files if ( $param_name =~ /ref_model_inc_before_class/i ) { $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; my $ref_model_name = $1; check_inc_file($3); $ref_model_inc_before_class{$ref_model_name} = $3; $ref_model_inc_before_inline{$ref_model_name} = $5 if ($5); print LOGFILE "ref_model_inc_before_class = $param_value\n"; } if ( $param_name =~ /ref_model_inc_inside_class/i ) { $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; my $ref_model_name = $1; check_inc_file($3); $ref_model_inc_inside_class{$ref_model_name} = $3; $ref_model_inc_inside_inline{$ref_model_name} = $5 if ($5); print LOGFILE "ref_model_inc_inside_class = $param_value\n"; } if ( $param_name =~ /ref_model_inc_after_class/i ) { $param_value =~ /\s*(\w+)(\s+|\s*,\s*)([\w\.]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; my $ref_model_name = $1; check_inc_file($3); $ref_model_inc_after_class{$ref_model_name} = $3; $ref_model_inc_after_inline{$ref_model_name} = $5 if ($5); print LOGFILE "ref_model_inc_after_class = $param_value\n"; } #Acceleration-ready transactors if ( $param_name =~ /dual_top/i ) { $dual_top = uc $param_value; print LOGFILE "dual_top = $param_value\n"; } if ( $param_name =~ /split_transactors/i ) { $split_transactors = uc $param_value; print LOGFILE "split_transactors = $param_value\n"; } } } unless ( $tbname ) { $tbname = "top"; } printf LOGFILE "prefix for top-level names: $tbname\n"; close TH; } #end parse_common sub after_parse_common { if ( defined $top_env_generate_methods_after_class && $top_env_generate_methods_after_class eq "NO" ) { if ( defined $top_env_prepend_to_build_phase ) { 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"; } if ( defined $top_env_append_to_build_phase ) { 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"; } if ( defined $top_env_append_to_connect_phase ) { 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"; } if ( defined $top_env_append_to_run_phase ) { 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"; } } if ( defined $test_generate_methods_after_class && $test_generate_methods_after_class eq "NO" ) { if ( defined $test_prepend_to_build_phase ) { die "ERROR in ${common_tpl_fname}. test_prepend_to_build_phase cannot be used in combination with test_generate_methods_after_class = no"; } if ( defined $test_append_to_build_phase ) { die "ERROR in ${common_tpl_fname}. test_append_to_build_phase cannot be used in combination with test_generate_methods_after_class = no"; } } if ( $split_transactors eq "YES" ) { $dual_top = "YES"; } } sub deal_with_deprecated_reg_template { if (defined($flag_regmodel_file)) { # With -x regmodel_file, force the script to read the deprecated register model template file reg.tpl if it exists $reg_template = "reg.tpl"; } parse_reg_template() if ( defined $reg_template and -e $reg_template ); if ( $regmodel ) { unless ( defined $top_reg_block_type ) { warning_prompt("-r switch given on command line but top-level regmodel block type has not been set"); } } # 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) if ( defined $top_reg_block_type ) { $regmodel = 1 } print LOGFILE "\$regmodel = $regmodel\n"; } sub parse_reg_template { # 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"; print LOGFILE "\nParsing reg.tpl ...\n\n"; open( TH, $reg_template ) || die "Exiting due to Error: can't open template: ${reg_template}\n"; for ( ; ; ) { my $line; undef $!; unless ( defined( $line = <TH> ) ) { die $! if $!; last; # reached EOF } #next if ($line =~ m/^#/); #comment line starts with "#" next if ( $line =~ m/\s*#/ ); #comment line starts with "#" next if ( $line =~ m/^\s\s*$/ ); #blank line $line =~ /^\s*(\w+)\s*=\s*(.+?)\s*$/ or die "Exiting due to Error: bad entry in line $. of ${reg_template}: $line\n"; my $param_name = $1; my $param_value = $2; #check for sub-blocks if ( $param_name =~ /rm_sub_block/i or $param_name =~ /regmodel_sub_block/i) { $param_value =~ /\s*(\w+)(\s+|\s*,\s*)(\w+)/ or die "Exiting due to Error: bad entry in line $. of ${reg_template}: $line\n"; $reg_access_block_type{$3} = $1; } #check for register model if ( $param_name =~ /rm_name/i or $param_name =~ /regmodel_name/i ) { unless ( defined $top_reg_block_type and $top_reg_block_type ne $param_value) { $top_reg_block_type = $param_value; } else { warning_prompt("Top-level regmodel block type set to $param_value in ${reg_template} but already set to $top_reg_block_type"); } print LOGFILE "regmodel_name: $top_reg_block_type\n"; } #check for regmodel file if ( $param_name =~ /rm_file/i or $param_name =~ /regmodel_file/i) { check_file($param_value); unless ( $param_value ne $regmodel_file and $regmodel_file ne "regmodel.sv" ) { $regmodel_file = $param_value; } else { warning_prompt("regmodel_file set to $param_value in ${reg_template} but already set to $regmodel_file"); } print LOGFILE "regmodel_file: $regmodel_file\n"; } } print LOGFILE "\n"; close TH; } #end parse_reg_template sub handle_minus_x_flag { if (defined($flag_dut_source_path)) { print $dut_path . "\n"; exit; } if (defined($flag_inc_path)) { print $inc_path . "\n"; exit; } if (defined($flag_project)) { print $project . "\n"; exit; } if (defined($flag_regmodel_file)) { if ( $regmodel ) { print $regmodel_file . "\n"; } else { print "\n"; } exit; } } sub create_directories_and_copy_files { #create backup of existing project directory if (-e $project && $backup ne "NO"){ print "Copying backup of existing generated files from $project to ${project}.bak\n"; dircopy( $project, "${project}.bak" ) or die "$!\n"; } mkdir( $project, 0755 ); $dir = $project . "/sim"; mkdir( $dir, 0755 ); $dir = $project . "/tb"; mkdir( $dir, 0755 ); $dir = $project . "/tb/" . $tbname; mkdir( $dir, 0755 ); mkdir( $dir . "/sv", 0755 ); mkdir( $dir . "/sv", 0755 ); $dir = $project . "/tb/" . $tbname . "_tb"; mkdir( $dir, 0755 ); mkdir( $dir . "/sv", 0755 ); $dir = $project . "/tb/" . $tbname . "_test"; mkdir( $dir, 0755 ); mkdir( $dir . "/sv", 0755 ); $dir1 = $dut_path; $dut_tb_dir = "dut"; $dut_tb_path = $project . "/" . $dut_tb_dir; $dir2 = $dut_tb_path; #print LOGFILE "dut_path: $dut_path\n"; if ( ( -e $dir ) && $dir1 ne $dir2 ) { print "Copying dut files to $dir2\n"; dircopy( $dir1, $dir2 ) or die "$!\n"; } else { print LOGFILE "dut_path does not exist. Nothing to copy from DUT\n"; } if ( -e $inc_path ) { $dir1 = $inc_path; $dir2 = $project . "/tb/include"; print "Copying include files to $dir2\n"; dircopy( $dir1, $dir2 ) or die "$!\n"; } } sub parse_template { @agent_var_array = (); @agent_enum_array = (); @agent_meta_array = (); @agent_var_cnstr_array = (); @agent_port_array = (); @agent_clock_array = (); @agent_reset_array = (); $agent_seqr_class = ""; @config_var_array = (); $uvm_reg_data = ""; $uvm_reg_addr = ""; $uvm_reg_kind = ""; @additional_agents = (); $agent_has_env = "NO"; open( TH, $template_name ) || die "Exiting due to Error: can't open template: " . $template_name . "\n"; for ( ; ; ) { my $line; undef $!; unless ( defined( $line = <TH> ) ) { die $! if $!; last; # reached EOF } next if ( $line =~ m/^\s*#/ ); #comment line starts with "#" next if ( $line =~ m/^\s+$/ ); #blank line $line =~ s/(^.*?)#.*/$1/; #delete trailing comments $line =~ /^\s*(\w+)\s*=\s*(.*?)\s*$/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; my $param_name = $1; my $param_value = $2; #check for agent_name if ( $param_name =~ /agent_name/i ) { print LOGFILE "agent_name: $line"; $agent_name = $param_value; if ( $agent_name eq "") { warning_prompt("agent_name is blank in ${template_name}"); } push( @agent_list, $agent_name ); # Set values and defaults that depend on agent name $number_of_instances{$agent_name} = 1; $tpl_fname{$agent_name} = $template_name; $agent_if = "${agent_name}_if"; $if_instance_names{$agent_if} = "${agent_if}_0"; $if_instance_names{"${agent_if}_0"} = "${agent_if}_0"; if ( $split_transactors eq "YES" ) { push( @all_agent_ifs, "${agent_name}_bfm" ); } else { push( @all_agent_ifs, $agent_if ); } } #number of instances of the agent and its interface if ( $param_name =~ /number_of_instances/i ) { $number_of_instances{$agent_name} = $param_value; print LOGFILE "number_of_instances = $param_value\n"; if ($param_value > 1) { for ( my $i = 1 ; $i < $param_value ; $i++ ) { $if_instance_names{"${agent_if}_${i}"} = "${agent_if}_${i}"; } } } #check if agent has its own env (default = NO) if ( $param_name =~ /agent_has_env/i ) { $agent_has_env = uc $param_value; } #check if other agents to be added to same env if ( $param_name =~ /additional_agent/i ) { push @additional_agents, $param_value; unless ( exists $agent_parent{$param_value} ) { $agent_parent{$param_value} = $agent_name; } else { 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}"); } } #check for uvm_seqr_class if ( $param_name =~ /uvm_seqr_class/i ) { $agent_seqr_class = $param_value; } #check for active/passive agent if ( $param_name =~ /agent_is_active/i ) { my $value = uc $param_value; if ( $value ne "UVM_ACTIVE" && $value ne "UVM_PASSIVE" ) { warning_prompt("agent_is_active must be either UVM_ACTIVE or UVM_PASSIVE in template file: ${template_name}"); } $agent_is_active{$agent_name} = $value; } #check for agent checks_enable (default = YES) if ( $param_name =~ /agent_checks_enable/i ) { $agent_checks_enable{$agent_name} = uc $param_value; } #check for agent coverage_enable (default = YES) if ( $param_name =~ /agent_coverage_enable/i ) { $agent_coverage_enable{$agent_name} = uc $param_value; } #check for trans_item if ( $param_name =~ /trans_item/i ) { $agent_item = $param_value; print LOGFILE "trans_item= $agent_item\n"; $agent_item_types{$agent_name} = $agent_item; } #check for trans_var if ( $param_name =~ /trans_var$/i ) { print LOGFILE "trans_var: $param_value\n"; push @agent_var_array, $param_value } #check for trans_enum and trans_meta if ( $param_name =~ /trans_enum_var$/i ) { print LOGFILE "trans_enum_var: $param_value\n"; push @agent_var_array, $param_value; push @agent_enum_array, $param_value; } if ( $param_name =~ /trans_meta$/i ) { print LOGFILE "trans_meta: $param_value\n"; push @agent_meta_array, $param_value; } if ( $param_name =~ /trans_enum_meta$/i) { print LOGFILE "trans_enum_meta: $param_value\n"; push @agent_meta_array, $param_value; push @agent_enum_array, $param_value; } #check for trans_var_constraint if ( $param_name =~ /trans_var_constraint/i ) { print LOGFILE "trans_var_constraint: $param_value\n"; push @agent_var_cnstr_array, $param_value; } #check for config_var if ( $param_name =~ /config_var$/i ) { print LOGFILE "config_var: $param_value\n"; push @config_var_array, $param_value; } #check for agent sequence include file if ( $param_name =~ /agent_seq_inc/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_seq_inc{$agent_name} = $1; $agent_seq_inc_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_seq_inc = $param_value\n"; } #check for agent include file if ( $param_name =~ /agent_generate_methods_inside_class/i ) { $agent_generate_methods_inside_class{$agent_name} = uc $param_value; print LOGFILE "agent_generate_methods_inside_class = $param_value\n"; } if ( $param_name =~ /agent_generate_methods_after_class/i ) { $agent_generate_methods_after_class{$agent_name} = uc $param_value; print LOGFILE "agent_generate_methods_after_class = $param_value\n"; } if ( $param_name =~ /agent_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_inc_before_class{$agent_name} = $1; $agent_inc_before_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_inc_before_class = $param_value\n"; } if ( $param_name =~ /agent_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_inc_inside_class{$agent_name} = $1; $agent_inc_inside_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_inc_inside_class = $param_value\n"; } if ( $param_name =~ /agent_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_inc_after_class{$agent_name} = $1; $agent_inc_after_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_inc_after_class = $param_value\n"; } if ( $param_name =~ /agent_inc_inside_bfm/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_inc_inside_bfm{$agent_name} = $1; $agent_inc_inside_bfm_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_inc_inside_bfm = $param_value\n"; } if ( $param_name =~ /agent_prepend_to_build_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_prepend_to_build_phase{$agent_name} = $1; $agent_prepend_to_build_phase_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_prepend_to_build_phase = $param_value\n"; } if ( $param_name =~ /agent_append_to_build_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_append_to_build_phase{$agent_name} = $1; $agent_append_to_build_phase_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_append_to_build_phase = $param_value\n"; } if ( $param_name =~ /agent_append_to_connect_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_append_to_connect_phase{$agent_name} = $1; $agent_append_to_connect_phase_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_append_to_connect_phase = $param_value\n"; } if ( $param_name =~ /agent_copy_config_vars/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_copy_config_vars{$agent_name} = $1; $agent_copy_config_vars_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_copy_config_vars = $param_value\n"; } #check for agent environment sequence include file if ( $param_name =~ /agent_env_seq_inc/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_env_seq_inc{$agent_name} = $1; $agent_env_seq_inc_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_env_seq_inc = $param_value\n"; } #check for agent env include file if ( $param_name =~ /agent_env_generate_methods_inside_class/i ) { $agent_env_generate_methods_inside_class{$agent_name} = uc $param_value; print LOGFILE "agent_env_generate_methods_inside_class = $param_value\n"; } if ( $param_name =~ /agent_env_generate_methods_after_class/i ) { $agent_env_generate_methods_after_class{$agent_name} = uc $param_value; print LOGFILE "agent_env_generate_methods_after_class = $param_value\n"; } if ( $param_name =~ /agent_env_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_env_inc_before_class{$agent_name} = $1; $agent_env_inc_before_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_env_inc_before_class = $param_value\n"; } if ( $param_name =~ /agent_env_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_env_inc_inside_class{$agent_name} = $1; $agent_env_inc_inside_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_env_inc_inside_class = $param_value\n"; } if ( $param_name =~ /agent_env_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_env_inc_after_class{$agent_name} = $1; $agent_env_inc_after_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_env_inc_after_class = $param_value\n"; } if ( $param_name =~ /agent_env_prepend_to_build_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_env_prepend_to_build_phase{$agent_name} = $1; $agent_env_prepend_to_build_phase_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_env_prepend_to_build_phase = $param_value\n"; } if ( $param_name =~ /agent_env_append_to_build_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_env_append_to_build_phase{$agent_name} = $1; $agent_env_append_to_build_phase_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_env_append_to_build_phase = $param_value\n"; } if ( $param_name =~ /agent_env_append_to_connect_phase/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_env_append_to_connect_phase{$agent_name} = $1; $agent_env_append_to_connect_phase_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_env_append_to_connect_phase = $param_value\n"; } if ( $param_name =~ /adapter_generate_methods_inside_class/i ) { $agent_adapter_generate_methods_inside_class{$agent_name} = uc $param_value; print LOGFILE "adapter_generate_methods_inside_class = $param_value\n"; } if ( $param_name =~ /adapter_generate_methods_after_class/i ) { $agent_adapter_generate_methods_after_class{$agent_name} = uc $param_value; print LOGFILE "adapter_generate_methods_after_class = $param_value\n"; } if ( $param_name =~ /adapter_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_adapter_inc_before_class{$agent_name} = $1; $agent_adapter_inc_before_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_adapter_inc_before_class = $param_value\n"; } if ( $param_name =~ /adapter_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_adapter_inc_inside_class{$agent_name} = $1; $agent_adapter_inc_inside_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_adapter_inc_inside_class = $param_value\n"; } if ( $param_name =~ /adapter_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_adapter_inc_after_class{$agent_name} = $1; $agent_adapter_inc_after_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_adapter_inc_after_class = $param_value\n"; } if ( $param_name =~ /byo_interface/i ) { $byo_interface{$agent_name} = $param_value; print LOGFILE "byo_interface = $param_value\n"; } if ( $param_name =~ /generate_interface_instance/i ) { $generate_interface_instance{$agent_name} = uc $param_value; print LOGFILE "generate_interface_instance = $param_value\n"; } if ( $param_name =~ /if_inc_inside_interface/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $if_inc_inside_interface{$agent_name} = $1; $if_inc_inside_inline{$agent_name} = $3 if ($3); print LOGFILE "if_inc_inside_interface = $param_value\n"; } if ( $param_name =~ /trans_generate_methods_inside_class/i ) { $agent_trans_generate_methods_inside_class{$agent_name} = uc $param_value; print LOGFILE "trans_generate_methods_inside_class = $param_value\n"; } if ( $param_name =~ /trans_generate_methods_after_class/i ) { $agent_trans_generate_methods_after_class{$agent_name} = uc $param_value; print LOGFILE "trans_generate_methods_after_class = $param_value\n"; } if ( $param_name =~ /trans_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_trans_inc_before_class{$agent_name} = $1; $agent_trans_inc_before_inline{$agent_name} = $3 if ($3); print LOGFILE "trans_inc_before_class = $param_value\n"; } if ( $param_name =~ /trans_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_trans_inc_inside_class{$agent_name} = $1; $agent_trans_inc_inside_inline{$agent_name} = $3 if ($3); print LOGFILE "trans_inc_inside_class = $param_value\n"; } if ( $param_name =~ /trans_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_trans_inc_after_class{$agent_name} = $1; $agent_trans_inc_after_inline{$agent_name} = $3 if ($3); print LOGFILE "trans_inc_after_class = $param_value\n"; } if ( $param_name =~ /agent_config_generate_methods_inside_class/i ) { $agent_config_generate_methods_inside_class{$agent_name} = uc $param_value; print LOGFILE "agent_config_generate_methods_inside_class = $param_value\n"; } if ( $param_name =~ /agent_config_generate_methods_after_class/i ) { $agent_config_generate_methods_after_class{$agent_name} = uc $param_value; print LOGFILE "agent_config_generate_methods_after_class = $param_value\n"; } if ( $param_name =~ /agent_config_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_config_inc_before_class{$agent_name} = $1; $agent_config_inc_before_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_config_inc_before_class = $param_value\n"; } if ( $param_name =~ /agent_config_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_config_inc_inside_class{$agent_name} = $1; $agent_config_inc_inside_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_config_inc_inside_class = $param_value\n"; } if ( $param_name =~ /agent_config_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_config_inc_after_class{$agent_name} = $1; $agent_config_inc_after_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_config_inc_after_class = $param_value\n"; } #check for agent coverpoint include file if ( $param_name =~ /agent_cover_generate_methods_inside_class/i ) { $agent_cover_generate_methods_inside_class{$agent_name} = uc $param_value; print LOGFILE "agent_cover_generate_methods_inside_class = $param_value\n"; } if ( $param_name =~ /agent_cover_generate_methods_after_class/i ) { $agent_cover_generate_methods_after_class{$agent_name} = uc $param_value; print LOGFILE "agent_cover_generate_methods_after_class = $param_value\n"; } if ( $param_name =~ /agent_cover_inc\b/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_cover_inc{$agent_name} = $1; $agent_cover_inc_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_cover_inc = $param_value\n"; } if ( $param_name =~ /agent_cover_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_cover_inc_before_class{$agent_name} = $1; $agent_cover_inc_before_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_cover_inc_before_class = $param_value\n"; } if ( $param_name =~ /agent_cover_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_cover_inc_inside_class{$agent_name} = $1; $agent_cover_inc_inside_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_cover_inc_inside_class = $param_value\n"; } if ( $param_name =~ /agent_cover_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_cover_inc_after_class{$agent_name} = $1; $agent_cover_inc_after_inline{$agent_name} = $3 if ($3); print LOGFILE "agent_cover_inc_after_class = $param_value\n"; } #check for driver include file if ( $param_name =~ /driver_inc\b/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_driv_inc{$agent_name} = $1; $agent_driv_inc_inline{$agent_name} = $3 if ($3); print LOGFILE "driver_inc = $param_value\n"; } if ( $param_name =~ /driver_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_driv_inc_before_class{$agent_name} = $1; $agent_driv_inc_before_inline{$agent_name} = $3 if ($3); print LOGFILE "driver_inc_before_class = $param_value\n"; } if ( $param_name =~ /driver_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_driv_inc_inside_class{$agent_name} = $1; $agent_driv_inc_inside_inline{$agent_name} = $3 if ($3); print LOGFILE "driver_inc_inside_class = $param_value\n"; } if ( $param_name =~ /driver_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_driv_inc_after_class{$agent_name} = $1; $agent_driv_inc_after_inline{$agent_name} = $3 if ($3); print LOGFILE "driver_inc_after_class = $param_value\n"; } #check for monitor include file if ( $param_name =~ /monitor_inc\b/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_mon_inc{$agent_name} = $1; $agent_mon_inc_inline{$agent_name} = $3 if ($3); print LOGFILE "monitor_inc = $param_value\n"; } if ( $param_name =~ /monitor_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_mon_inc_before_class{$agent_name} = $1; $agent_mon_inc_before_inline{$agent_name} = $3 if ($3); print LOGFILE "monitor_inc_before_class = $param_value\n"; } if ( $param_name =~ /monitor_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_mon_inc_inside_class{$agent_name} = $1; $agent_mon_inc_inside_inline{$agent_name} = $3 if ($3); print LOGFILE "monitor_inc_inside_class = $param_value\n"; } if ( $param_name =~ /monitor_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_mon_inc_after_class{$agent_name} = $1; $agent_mon_inc_after_inline{$agent_name} = $3 if ($3); print LOGFILE "monitor_inc_after_class = $param_value\n"; } #check for sequencer include file if ( $param_name =~ /sequencer_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_seqr_inc_before_class{$agent_name} = $1; $agent_seqr_inc_before_inline{$agent_name} = $3 if ($3); print LOGFILE "sequencer_inc_before_class = $param_value\n"; } if ( $param_name =~ /sequencer_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_seqr_inc_inside_class{$agent_name} = $1; $agent_seqr_inc_inside_inline{$agent_name} = $3 if ($3); print LOGFILE "sequencer_inc_inside_class = $param_value\n"; } if ( $param_name =~ /sequencer_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_seqr_inc_after_class{$agent_name} = $1; $agent_seqr_inc_after_inline{$agent_name} = $3 if ($3); print LOGFILE "sequencer_inc_after_class = $param_value\n"; } #check for if_port if ( $param_name =~ /if_port/i ) { my $agent_port = $param_value; push @agent_port_array, $agent_port; print LOGFILE "if_port = $param_value\n"; } #check for if_clock if ( $param_name =~ /if_clock/i ) { my $agent_clock = $param_value; push @agent_clock_array, $agent_clock; $env_clock_list = $env_clock_list ? "$env_clock_list $agent_name $agent_clock" : "$agent_name $agent_clock"; print LOGFILE "env_clock_list: $env_clock_list\n"; } @clist = split( /\s+/, $env_clock_list ); foreach $i ( 0 .. @clist-1 ) { if ( $clist[$i] ne "" ) { print LOGFILE "clist[$i]: $clist[$i]\n"; } } #check for if_reset if ( $param_name =~ /if_reset/i ) { $agent_reset = $param_value; print LOGFILE "IF_RESET: $agent_reset\n"; push @agent_reset_array, $agent_reset; $env_reset_list = $env_reset_list ? "$env_reset_list $agent_name $agent_reset" : "$agent_name $agent_reset"; print LOGFILE "env_reset_list: $env_reset_list\n"; } @rlist = split( /\s+/, $env_reset_list ); foreach $i ( 0 .. @rlist-1 ) { if ( $rlist[$i] ne "" ) { print LOGFILE "rlist[$i]: $rlist[$i]\n"; } } #check for reg_access (gives addr map in uvm_reg) if ( $param_name =~ /reg_access_name/i ) { 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"; $param_value =~ /\s*(\w+)(\s+|\s*,\s*)(\w+)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; unless ( exists $reg_access_mode{$agent_name} and $reg_access_mode{$agent_name} ne $3 ) { $reg_access_mode{$agent_name} = $3; } else { 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})"); } print LOGFILE "reg_access_name: $param_value\n"; } if ( $param_name =~ /reg_access_block_type/i ) { $param_value =~ /\s*(\w+)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; unless ( exists $reg_access_block_type{$agent_name} and $reg_access_block_type{$agent_name} ne $1 ) { $reg_access_block_type{$agent_name} = $1; } else { 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})"); } print LOGFILE "reg_access_block_type: $1\n"; } if ( $param_name =~ /reg_access_block_instance/i ) { $param_value =~ /\s*([\w\.]*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; my $instance = $1; if ( $instance ne "" ) { if ( substr($instance, 0, 1) ne "." ) { $instance = ".$instance"; } } unless ( exists $reg_access_instance{$agent_name} and $reg_access_instance{$agent_name} ne $instance ) { $reg_access_instance{$agent_name} = $instance; } else { 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})"); } print LOGFILE "reg_access_block_instance: $instance\n"; } if ( $param_name =~ /reg_access_map/i ) { $param_value =~ /\s*(\w+)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; $reg_access_map{$agent_name} = $1; print LOGFILE "reg_access_map: $1\n"; } if ( $param_name =~ /reg_access_mode/i ) { $param_value =~ /\s*(\w+)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; unless ( exists $reg_access_mode{$agent_name} and $reg_access_mode{$agent_name} ne $1 ) { $reg_access_mode{$agent_name} = $1; } else { 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})"); } print LOGFILE "reg_access_mode: $1\n"; } #check for uvm_reg to bus mappings if ( $param_name =~ /uvm_reg_data/i ) { $uvm_reg_data = $param_value; } if ( $param_name =~ /uvm_reg_addr/i ) { $uvm_reg_addr = $param_value; } if ( $param_name =~ /uvm_reg_kind/i ) { $uvm_reg_kind = $param_value; } #check for register sequence include file (an alias for agent_env_seq_inc) if ( $param_name =~ /reg_seq_inc/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $agent_env_seq_inc{$agent_name} = $1; $agent_env_seq_inc_inline{$agent_name} = $3 if ($3); print LOGFILE "reg_seq_inc = $param_value\n"; } #check for register coverpoint include file if ( $param_name =~ /reg_cover_generate_methods_inside_class/i ) { $reg_cover_generate_methods_inside_class{$agent_name} = uc $param_value; print LOGFILE "reg_cover_generate_methods_inside_class = $param_value\n"; } if ( $param_name =~ /reg_cover_generate_methods_after_class/i ) { $reg_cover_generate_methods_after_class{$agent_name} = uc $param_value; print LOGFILE "reg_cover_generate_methods_after_class = $param_value\n"; } if ( $param_name =~ /reg_cover_inc\b/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $reg_cover_inc{$agent_name} = $1; $reg_cover_inc_inline{$agent_name} = $3 if ($3); print LOGFILE "reg_cover_inc = $param_value\n"; } if ( $param_name =~ /reg_cover_inc_before_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $reg_cover_inc_before_class{$agent_name} = $1; $reg_cover_inc_before_inline{$agent_name} = $3 if ($3); print LOGFILE "reg_cover_inc_before_class = $param_value\n"; } if ( $param_name =~ /reg_cover_inc_inside_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $reg_cover_inc_inside_class{$agent_name} = $1; $reg_cover_inc_inside_inline{$agent_name} = $3 if ($3); print LOGFILE "reg_cover_inc_inside_class = $param_value\n"; } if ( $param_name =~ /reg_cover_inc_after_class/i ) { $param_value =~ /\s*([\w\.\/]+)\s*(,|\s)?\s*(\w*)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; check_inc_file($1); $reg_cover_inc_after_class{$agent_name} = $1; $reg_cover_inc_after_inline{$agent_name} = $3 if ($3); print LOGFILE "reg_cover_inc_after_class = $param_value\n"; } #check for factory overrides if ( $param_name =~ /agent_factory_set/i ) { $param_value =~ /\s*(\w+)(\s+|\s*,\s*)(\w+)/ or die "Exiting due to Error: bad entry in line $. of ${template_name}: $line\n"; $agent_factory_set{$1} = $3; } } # End of file parsing loop close TH; } #end parse_template sub after_parse_template { if ( exists $reg_access_mode{$agent_name} ) { $bus2reg_map{$agent_name} = { 'data' => $uvm_reg_data, 'addr' => $uvm_reg_addr, 'kind' => $uvm_reg_kind }; if ( @additional_agents ) { 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}"); } unless ( exists $reg_access_instance{$agent_name} ) { $reg_access_instance{$agent_name} = ".${agent_name}"; } unless ( exists $reg_access_map{$agent_name} ) { $reg_access_map{$agent_name} = "${agent_name}_map"; } unless ( exists $reg_access_block_type{$agent_name} ) { 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}"); } if ( $number_of_instances{$agent_name} > 1 ) { warning_prompt("Agent $agent_name uses reg_access_* but has number_of_instances = $number_of_instances{$agent_name} in ${template_name}." . " reg_access_instance and reg_access_map will get the suffix _N. This will change in future versions of the generator."); } if ( $agent_has_env eq "NO" ) { print "Forcing agent_has_env = yes for agent ${agent_name} because the agent uses register access\n"; } $agent_has_env = "YES"; if ( exists $agent_is_active{$agent_name} and $agent_is_active{$agent_name} eq "UVM_PASSIVE" ) { warning_prompt("Agent $agent_name uses reg_access_* but has agent_is_active = UVM_PASSIVE in template file: ${template_name}"); } } else { if ( exists $reg_access_block_type{$agent_name} ) { 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}"); } if ( exists $reg_access_map{$agent_name} ) { warning_prompt("reg_access_map is set without setting reg_access_name or reg_access_mode in template file: ${template_name}"); } if ( exists $reg_access_instance{$agent_name} ) { warning_prompt("reg_access_block_instance is set without setting reg_access_name or reg_access_mode in template file: ${template_name}"); } } # Build hash of agent types indexed by agent instance name for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent_name}); my $instance; if ( $agent_has_env eq "NO" ) { $instance = "m_${agent_name}${suffix}_agent"; } else { $instance = "m_${agent_name}_env.m_${agent_name}${suffix}_agent"; } $agent_type_by_inst{$instance} = $agent_name; push @agent_instance_names, $instance; } if ( $agent_has_env eq "NO" ) { push( @stand_alone_agents, $agent_name ); } else { push( @env_list, "${agent_name}_env" ); } if ( @additional_agents ) { # Array of additional_agents print LOGFILE "${agent_name}_env has other agents: @additional_agents\n"; # Hash %env_agents needs to store a copy of the @additional_agents array per-agent my @copy_array = @additional_agents; $env_agents{"${agent_name}_env"} = \@copy_array; if ( $agent_has_env eq "NO" ) { warning_prompt("Agent ${agent_name} has an additional_agent (@additional_agents) and hence should have agent_has_env = yes"); } foreach my $extra_agent ( @additional_agents ) { my $instance; $instance = "m_${agent_name}_env.m_${extra_agent}_agent"; $agent_type_by_inst{$instance} = $agent_name; push @agent_instance_names, $instance; } } if ( exists $agent_generate_methods_after_class{$agent_name} && $agent_generate_methods_after_class{$agent_name} eq "NO" ) { if ( exists $agent_prepend_to_build_phase{$agent_name} ) { die "ERROR in ${template_name}. agent_prepend_to_build_phase cannot be used in combination with agent_generate_methods_after_class = no"; } if ( exists $agent_append_to_build_phase{$agent_name} ) { die "ERROR in ${template_name}. agent_append_to_build_phase cannot be used in combination with agent_generate_methods_after_class = no"; } if ( exists $agent_append_to_connect_phase{$agent_name} ) { die "ERROR in ${template_name}. agent_append_to_connect_phase cannot be used in combination with agent_generate_methods_after_class = no"; } } unless ( $agent_seqr_class =~ /y|yes/i ) { if ( exists $agent_seqr_inc_before_class{$agent_name} or exists $agent_seqr_inc_inside_class{$agent_name} or exists $agent_seqr_inc_after_class{$agent_name} ) { 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"; } } if ( exists $agent_env_generate_methods_after_class{$agent_name} && $agent_env_generate_methods_after_class{$agent_name} eq "NO" ) { if ( exists $agent_env_prepend_to_build_phase{$agent_name} ) { die "ERROR in ${template_name}. agent_env_prepend_to_build_phase cannot be used in combination with agent_env_generate_methods_after_class = no"; } if ( exists $agent_env_append_to_build_phase{$agent_name} ) { die "ERROR in ${template_name}. agent_env_append_to_build_phase cannot be used in combination with agent_env_generate_methods_after_class = no"; } if ( exists $agent_env_append_to_connect_phase{$agent_name} ) { die "ERROR in ${template_name}. agent_env_append_to_connect_phase cannot be used in combination with agent_env_generate_methods_after_class = no"; } } } sub check_common_pkg { my ($fname) = @_; if (-e "${dut_path}/${fname}" ) { get_pkg_name("${dut_path}/${fname}"); } else { warning_prompt("common_pkg file ${fname} specified in ${common_tpl_fname} not found in ${dut_path}"); } } sub get_pkg_name { my ($fname_with_path) = @_; my $line; open( LFH, $fname_with_path ) or die "CANNOT OPEN FILE ${fname_with_path}!\n"; SKIP_BL: while (<LFH>) { if (/\w+/) { $line = $_; last SKIP_BL; } } $line or die "Exiting due to Error: common package file $fname_with_path exists but is empty\n"; FIND: while ($line) { while ($line) { if ( $line =~ m!\s*//.*\n! ) { #comments - ignore $line = <LFH>; next FIND; } elsif ( $line =~ m/^\s*package\s+(\w+)\s*;/ ) { #package declaration $common_pkg = $1; print LOGFILE "get_pkg_name: found package name $common_pkg\n"; last FIND; } $line = <LFH>; } } #FIND } sub check_common_env_pkg { my ($fname) = @_; if (-e "${inc_path}/${fname}" ) { get_env_pkg_name("${inc_path}/${fname}"); } else { warning_prompt("common_env_pkg file ${fname} specified in ${common_tpl_fname} not found in ${inc_path}"); } } sub get_env_pkg_name { my ($fname_with_path) = @_; my $line; open( LFH, $fname_with_path ) or die "CANNOT OPEN FILE ${fname_with_path}!\n"; SKIP_BL: while (<LFH>) { if (/\w+/) { $line = $_; last SKIP_BL; } } $line or die "Exiting due to Error: common env package file $fname_with_path exists but is empty\n"; FIND: while ($line) { while ($line) { if ( $line =~ m!\s*//.*\n! ) { #comments - ignore $line = <LFH>; next FIND; } elsif ( $line =~ m/^\s*package\s+(\w+)\s*;/ ) { #package declaration $common_env_pkg = $1; print LOGFILE "get_env_pkg_name: found env package name $common_env_pkg\n"; last FIND; } $line = <LFH>; } } #FIND } sub extra_checking_for_additional_agents { foreach my $agent (@stand_alone_agents) { push( @top_env_agents, $agent ) unless grep( /$agent/, keys(%agent_parent) ); } # Check for agent with agent_has_env = yes being used as an additional_agent foreach my $agent (@agent_list) { if ( exists $agent_parent{$agent} ) { unless ( grep( /$agent/, @stand_alone_agents ) ) { warning_prompt("Agent ${agent} is used as an additional_agent (in $agent_parent{$agent}) and hence should itself have agent_has_env = no"); } if ( $number_of_instances{$agent} > 1 ) { warning_prompt("Agent ${agent} is used as an additional_agent (in $agent_parent{$agent}) and hence should itself have number_of_instances = 1"); } } } } sub calc_suffix { my ($i, $n) = @_; my $suffix; if ($n == 1) { $suffix = ""; } else { $suffix = "_${i}"; } return $suffix; } sub check_file { my ($fname) = @_; unless (-e "${fname}") { warning_prompt("SPECIFIED FILE $fname NOT FOUND"); } } sub check_inc_file { my ($fname) = @_; unless (-e "${inc_path}/${fname}") { warning_prompt("SPECIFIED INCLUDE FILE $fname NOT FOUND"); } } sub insert_inc_file { my ($indent, $fname, $inline, $flagname, $templatefile) = @_; if ( defined $fname) { my $fullname = "${project}/tb/include/${fname}"; #print "insert_inc_file, fname = ${fname}, inline = ${inline}\n"; if (-e $fullname) { if (defined $inline && uc($inline) eq "INLINE") { open( TH, $fullname ) || die "Exiting due to Error: can't open include file: " . $fullname . "\n"; print FH "${indent}// Start of inlined include file $fullname\n" if $flagname ne "file_header_inc"; for ( ; ; ) { my $line; undef $!; unless ( defined( $line = <TH> ) ) { die $! if $!; last; # reached EOF } print FH $indent .$line; } print FH "${indent}// End of inlined include file\n" if $flagname ne "file_header_inc"; print FH "\n"; } else { print FH "${indent}`include \"$fname\"\n"; print FH "\n"; } } } elsif ($flagname ne "") { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH "${indent}// You can insert code here by setting $flagname in file $templatefile\n\n"; } } } sub warning_prompt { my $message = "@_"; warn "WARNING! $message\n"; unless ($continue_on_warning) { print "Continue? (y/n) [n] "; <STDIN> =~ /y/i or die "UVM CODE NOT GENERATED DUE TO ERRORS!"; } } sub write_file_header { my ($fname,$descript) = @_; my $inline = "INLINE"; insert_inc_file("", $file_header_inc, $inline, "file_header_inc", $common_tpl_fname); unless ( defined $generate_file_header && $generate_file_header eq "NO" ) { print FH "//=============================================================================\n"; if ( defined $copyright ) { print FH "// $copyright\n"; print FH "//=============================================================================\n"; } print FH "// Project : " . $project . "\n"; print FH "//\n"; print FH "// File Name: $fname\n"; print FH "//\n"; print FH "// Author : Name : $author\n" if ( defined $author );; print FH "// Email : $email\n" if ( defined $email ); print FH "// Tel : $tel\n" if ( defined $tel ); print FH "// Dept : $dept\n" if ( defined $dept ); print FH "// Company: $company\n" if ( defined $company ); print FH "// Year : $year\n" if ( defined $year ); print FH "//\n"; print FH "// Version: $version\n"; print FH "//\n"; print FH "// Code created by Easier UVM Code Generator version $VERNUM on $date\n"; print FH "//=============================================================================\n"; print FH "// Description: $descript\n"; print FH "//=============================================================================\n"; print FH "\n"; } } my @pp_list1; my @pp_list2; my @pp_list3; sub align { my ($arg1,$arg2,$arg3) = @_; push @pp_list1, $arg1; push @pp_list2, $arg2; push @pp_list3, $arg3; } sub gen_aligned { pretty_print(\@pp_list1, \@pp_list2, \@pp_list3); @pp_list1 = (); @pp_list2 = (); @pp_list3 = (); } sub pretty_print { # Can pretty-print 2 columns (args 1 and 2) or 3 columns (args 1, 2, and 3) # If the string in the 2nd arg is empty, the first string is printed verbatim with no \n added my ($arg1ref, $arg2ref, $arg3ref) = @_; my @string1 = @{$arg1ref}; my @string2 = @{$arg2ref}; my @string3 = @{$arg3ref}; my $string1_len = @string1; my $string2_len = @string2; my $string3_len = @string3; unless ($string1_len == $string2_len and ($string2_len == $string3_len or $string3_len == 0)) { die "Parameters to pretty_print are wrong"; } my $maxlen1 = 0; for ($i = 0; $i < @string1; $i++) { if ( length($string2[$i]) > 0 ) { my $txt = $string1[$i]; if (length($txt) > $maxlen1) { $maxlen1 = length($txt); } } } my $maxlen2 = 0; foreach $ele (@string2) { if (length($ele) > $maxlen2) { $maxlen2 = length($ele); } } for ($i = 0; $i < @string1; $i++) { my $txt = $string1[$i]; print FH $txt; if (length ($string2[$i]) > 0) { for (1 .. $maxlen1 - length($txt)) { print FH " "; } $txt = $string2[$i]; print FH $txt; if ($string3_len > 0) { for (1 .. $maxlen2 - length($txt)) { print FH " "; } print FH $string3[$i]; } print FH "\n"; } } } sub gen_if { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_if.sv" ) || die "Exiting due to Error: can't open interface: $agent_name"; write_file_header "${agent_name}_if.sv", "Signal interface for agent $agent_name"; print FH "`ifndef " . uc($agent_name) . "_IF_SV\n"; print FH "`define " . uc($agent_name) . "_IF_SV\n"; print FH "\n"; print FH "interface ${agent_if}(); \n"; print FH "\n"; print FH " timeunit $timeunit;\n"; print FH " timeprecision $timeprecision;\n"; print FH "\n"; print FH " import ${common_pkg}::*;\n" if $common_pkg; print FH " import ${common_env_pkg}::*;\n" if $common_env_pkg; print FH " import ${agent_name}_pkg::*;\n"; print FH "\n"; foreach $port_decl (@agent_port_array) { print FH " ${port_decl}\n"; } print FH "\n"; print FH " // You can insert properties and assertions here\n"; print FH "\n"; insert_inc_file(" ", $if_inc_inside_interface{$agent_name}, $if_inc_inside_inline{$agent_name}, "if_inc_inside_interface", $tpl_fname{$agent_name}); print FH "endinterface : ${agent_if}\n"; print FH "\n"; print FH "`endif // " . uc($agent_name) . "_IF_SV\n"; print FH "\n"; close(FH); } #end gen_if sub gen_bfm { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_bfm.sv" ) || die "Exiting due to Error: can't open interface: $agent_name"; write_file_header "${agent_name}_bfm.sv", "Synthesizable BFM for agent $agent_name"; print FH "`ifndef " . uc($agent_name) . "_BFM_SV\n"; print FH "`define " . uc($agent_name) . "_BFM_SV\n"; print FH "\n"; my $interface_type; if ( exists $byo_interface{$agent_name} ) { $interface_type = $byo_interface{$agent_name}; } else { $interface_type = $agent_if; } print FH "interface ${agent_name}_bfm(${interface_type} if_port); \n"; print FH "\n"; print FH " timeunit $timeunit;\n"; print FH " timeprecision $timeprecision;\n"; print FH "\n"; print FH " import ${common_pkg}::*;\n" if $common_pkg; print FH " import ${common_env_pkg}::*;\n" if $common_env_pkg; print FH " import ${agent_name}_pkg::*;\n"; print FH "\n"; insert_inc_file(" ", $agent_inc_inside_bfm{$agent_name}, $agent_inc_inside_bfm_inline{$agent_name}, "agent_inc_inside_bfm", $tpl_fname{$agent_name}); print FH "endinterface : ${agent_name}_bfm\n"; print FH "\n"; print FH "`endif // " . uc($agent_name) . "_BFM_SV\n"; print FH "\n"; close(FH); } #end gen_bfm sub gen_seq_item { printf LOGFILE "AGENT-ITEM: $agent_item\n"; $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_" . $agent_item . ".sv" ) || die "Exiting due to Error: can't open data_item: $agent_item"; write_file_header "${agent_name}_seq_item.sv", "Sequence item for ${agent_name}_sequencer"; print FH "`ifndef " . uc($agent_name) . "_SEQ_ITEM_SV\n"; print FH "`define " . uc($agent_name) . "_SEQ_ITEM_SV\n"; print FH "\n"; 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}); print FH "class ${agent_item} extends uvm_sequence_item; \n"; print FH "\n"; print FH " `uvm_object_utils(" . $agent_item . ")\n"; print FH "\n"; 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"; print FH " // To exclude variables from compare, pack, and unpack methods, define them using trans_meta in file $tpl_fname{$agent_name}\n"; print FH "\n"; if (@agent_var_array) { print FH " // Transaction variables\n"; } foreach my $var_decl (@agent_var_array) { print FH " $var_decl\n"; } print FH "\n"; if (@agent_meta_array) { print FH " // Transaction metadata\n"; } foreach my $var_decl (@agent_meta_array) { print FH " $var_decl\n"; } print FH "\n"; if ( @agent_var_cnstr_array ) { my $cnstr_count = 0; foreach my $cnstr (@agent_var_cnstr_array) { print FH " constraint c$cnstr_count $cnstr\n"; $cnstr_count++; } print FH "\n"; } print FH " extern function new(string name = \"\");\n"; unless ( exists $agent_trans_generate_methods_inside_class{$agent_name} && $agent_trans_generate_methods_inside_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH " extern function void do_copy(uvm_object rhs);\n"; print FH " extern function bit do_compare(uvm_object rhs, uvm_comparer comparer);\n"; print FH " extern function void do_print(uvm_printer printer);\n"; print FH " extern function void do_record(uvm_recorder recorder);\n"; unless (defined $flag_nopack) { print FH " extern function void do_pack(uvm_packer packer);\n"; print FH " extern function void do_unpack(uvm_packer packer);\n"; } print FH " extern function string convert2string();\n"; } print FH "\n"; 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}); print FH "endclass : $agent_item \n"; print FH "\n"; print FH "\n"; print FH "function ${agent_item}::new(string name = \"\");\n"; print FH " super.new(name);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; @all_tx_vars = (); @non_local_tx_vars = (); @non_meta_tx_vars = (); %enum_var_types = (); %unpacked_bound = (); my $count = 1; PROC_VAR:foreach my $var_decl (@agent_var_array, @agent_meta_array) { print LOGFILE "var_decl=", $var_decl, "\n"; my $ismeta = ($count++ > @agent_var_array); if ( $var_decl =~ m/^const\s+/ ) { print "WARNING: CONSTANT TRANS_VAR $var_decl not adding to copy/compare functions!\n"; next PROC_VAR; } if ( $var_decl =~ m/^static\s+/ ) { print "WARNING: STATIC TRANS_VAR $var_decl not adding to copy/compare functions!\n"; next PROC_VAR; } if ( $var_decl =~ m/^typedef\s+/ ) { print LOGFILE "Found type definition $var_decl\n"; next PROC_VAR; } if ( $var_decl =~ m/^constraint\s+/ ) { print LOGFILE "Found constraint $var_decl\n"; next PROC_VAR; } if ( $var_decl =~ m/^\/\// ) { print LOGFILE "Found comment $var_decl\n"; next PROC_VAR; } my $islocal = ($var_decl =~ m/local|protected/); my $stripped_decl = $var_decl; $stripped_decl =~ s/\[/ \[/g; # Insert space before [ $stripped_decl =~ s/\]/\] /g; # Insert space after ] $stripped_decl =~ s/\[.+?:.+?\]//g; # Remove array bounds of the form [a:b] print LOGFILE "stripped_decl=", $stripped_decl, "\n"; @fields = split /[\s]+/, $stripped_decl; #split on space # get name of field to print, has to work with following examples # bit parity; // Variable is field 1 (parity) # rand bit [Dwidth - 1:0] payload []; // Variable is field 3 (payload) # local logic signed [3:0][7:0] vec; // Variable is field 4 (vec) my $pf = 0; # Type Variable is simplest case if ( $fields[$pf] =~ m/rand|local|protected/ ) { #starts with "rand", "local" or "protected" so skip $pf++; } if ( $fields[$pf] =~ m/rand|local|protected/ ) { #skip "rand local", "local rand", "rand protected" or "protected rand" modifier $pf++; } if ( $fields[$pf + 1] =~ m/signed|unsigned/ ) { #skip signed or unsigned modifier $pf++; } while ( $fields[$pf] =~ m/^\d+:\d+/ ) { #skip packed dimensions (i.e. bit [7:0] $pf++; } $pf++; # Should now point to the variable my $var_name = $fields[$pf]; $var_name =~ s/;//; #remove trailing ';' if ( (@fields > $pf + 1) && $fields[$pf + 1] =~ m/\[/ ) { # Found unpacked array dimension (e.g. type var [N] # Concatenate the remaining fields in case the unpacked range contained spaces was therefore split over multiple fields my $parse = ""; for ($i = $pf + 1; $i < @fields; $i++) { $parse = $parse . $fields[$i]; } $parse =~ /\[(.+)\].*/ or die "Exiting due to Error: ran out of steam trying to parse unpacked array dimension\n"; $unpacked_bound{$var_name} = $1; } push @all_tx_vars, $var_name; push @non_local_tx_vars, $var_name unless $islocal || $ismeta || ( exists $unpacked_bound{$var_name} ); push @non_meta_tx_vars, $var_name unless $ismeta; foreach $i ( @agent_enum_array ) { if ( $var_decl eq $i ) { $enum_var_types{$var_name} = $fields[$pf-1]; last; } } if ( $ismeta ) { print LOGFILE "METADATA type = $fields[$pf-1], var = $var_name\n"; } else { print LOGFILE "VARIABLE type = $fields[$pf-1], var = $var_name\n"; } } unless ( exists $agent_trans_generate_methods_after_class{$agent_name} && $agent_trans_generate_methods_after_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH "function void ${agent_item}::do_copy(uvm_object rhs);\n"; print FH " " . $agent_item . " rhs_;\n"; print FH " if (!\$cast(rhs_, rhs))\n"; print FH " `uvm_fatal(get_type_name(), \"Cast of rhs object failed\")\n"; print FH " super.do_copy(rhs);\n"; foreach $field ( @all_tx_vars ) { align(" ${field} ", "= rhs_.${field};", ""); } gen_aligned(); print FH "endfunction : do_copy\n"; print FH "\n"; print FH "\n"; print FH "function bit ${agent_item}::do_compare(uvm_object rhs, uvm_comparer comparer);\n"; print FH " bit result;\n"; print FH " " . $agent_item . " rhs_;\n"; print FH " if (!\$cast(rhs_, rhs))\n"; print FH " `uvm_fatal(get_type_name(), \"Cast of rhs object failed\")\n"; print FH " result = super.do_compare(rhs, comparer);\n"; foreach $field ( @non_meta_tx_vars ) { if ( exists $unpacked_bound{$field} ) { align(" for (int i = 0; i < $unpacked_bound{$field}; i++)\n", "", ""); align(" result &= comparer.compare_field(\"${field}\", ${field}[i], ", "rhs_.${field}[i], ", "\$bits(${field}[i]));"); } else { align(" result &= comparer.compare_field(\"${field}\", ${field}, ", "rhs_.${field}, ", "\$bits(${field}));"); } } gen_aligned(); print FH " return result;\n"; print FH "endfunction : do_compare\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_item}::do_print(uvm_printer printer);\n"; print FH " if (printer.knobs.sprint == 0)\n"; print FH " `uvm_info(get_type_name(), convert2string(), UVM_MEDIUM)\n"; print FH " else\n"; print FH " printer.m_string = convert2string();\n"; print FH "endfunction : do_print\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_item}::do_record(uvm_recorder recorder);\n"; print FH " super.do_record(recorder);\n"; print FH " // Use the record macros to record the item fields:\n"; foreach $field ( @all_tx_vars ) { if ( exists $unpacked_bound{$field} ) { align(" for (int i = 0; i < $unpacked_bound{$field}; i++)\n", "", ""); align(" `uvm_record_field({\"${field}_\",\$sformatf(\"%0d\",i)}, ", "${field}[i])", ""); } else { align(" `uvm_record_field(\"${field}\", ", "${field})", ""); } } gen_aligned(); print FH "endfunction : do_record\n"; print FH "\n"; print FH "\n"; unless (defined $flag_nopack) { print FH "function void ${agent_item}::do_pack(uvm_packer packer);\n"; print FH " super.do_pack(packer);\n"; foreach $field ( @non_meta_tx_vars ) { if ( exists $unpacked_bound{$field} ) { align(" `uvm_pack_sarray(${field})", " ", ""); } elsif ( exists $enum_var_types{$field} ) { align(" `uvm_pack_enum(${field})", " ", ""); } else { align(" `uvm_pack_int(${field})", " ", ""); } } gen_aligned(); print FH "endfunction : do_pack\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_item}::do_unpack(uvm_packer packer);\n"; print FH " super.do_unpack(packer);\n"; foreach $field ( @non_meta_tx_vars ) { if ( exists $unpacked_bound{$field} ) { align(" `uvm_unpack_sarray(${field})", " ", ""); } elsif ( exists $enum_var_types{$field} ) { align(" `uvm_unpack_enum(${field}, ", " $enum_var_types{$field})", ""); } else { align(" `uvm_unpack_int(${field})", " ", ""); } } gen_aligned(); print FH "endfunction : do_unpack\n"; print FH "\n"; print FH "\n"; } print FH "function string ${agent_item}::convert2string();\n"; print FH " string s;\n"; print FH " \$sformat(s, \"%s\\n\", super.convert2string());\n"; if ( @all_tx_vars > 0 ) { print FH " \$sformat(s, {\"%s\\n\",\n"; foreach $i ( 0 .. @all_tx_vars - 1) { $field = $all_tx_vars[$i]; my $terminator = ( $i < @all_tx_vars - 1 ) ? "," : "},"; my $formatting = exists $unpacked_bound{$field} ? "%p" : exists $enum_var_types{$field} ? "%s" : "'h%0h 'd%0d"; align(" \"${field} ", "= ${formatting}\\n\"${terminator}", ""); } gen_aligned(); print FH " get_full_name(),"; foreach $i ( 0 .. @all_tx_vars - 1) { $field = $all_tx_vars[$i]; if ( exists $unpacked_bound{$field} ) { print FH " ${field}"; } elsif ( exists $enum_var_types{$field} ) { print FH " ${field}.name"; } else { print FH " ${field}, ${field}"; } my $terminator = ( $i < @all_tx_vars - 1 ) ? "," : ");"; print FH "$terminator"; } } print FH "\n"; print FH " return s;\n"; print FH "endfunction : convert2string\n"; print FH "\n"; print FH "\n"; } 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}); print FH "`endif // " . uc($agent_name) . "_SEQ_ITEM_SV\n"; print FH "\n"; close(FH); } #end gen_data_item sub gen_driver { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_driver.sv" ) || die "Exiting due to Error: can't open driver: $agent_name"; write_file_header "${agent_name}_driver.sv", "Driver for $agent_name"; print FH "`ifndef " . uc($agent_name) . "_DRIVER_SV\n"; print FH "`define " . uc($agent_name) . "_DRIVER_SV\n"; print FH "\n"; 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}); print FH "class ${agent_name}_driver extends uvm_driver #(${agent_item});\n"; print FH "\n"; print FH " `uvm_component_utils(" . $agent_name . "_driver)\n"; print FH "\n"; my $interface_type; if ( $split_transactors eq "YES" ) { $interface_type = $agent_name . "_bfm"; } elsif ( exists $byo_interface{$agent_name} ) { $interface_type = $byo_interface{$agent_name}; } else { $interface_type = $agent_if; } print FH " virtual ${interface_type} vif;\n"; print FH "\n"; print FH " ${agent_name}_config m_config;\n"; print FH "\n"; print FH " extern function new(string name, uvm_component parent);\n"; if ( exists $agent_driv_inc{$agent_name} && -e "${project}/tb/include/$agent_driv_inc{$agent_name}" ) { print FH "\n"; print FH " // Methods run_phase and do_drive generated by setting driver_inc in file $tpl_fname{$agent_name}\n"; print FH " extern task run_phase(uvm_phase phase);\n"; print FH " extern task do_drive();\n"; } print FH "\n"; 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}); print FH "endclass : " . $agent_name . "_driver \n"; print FH "\n"; print FH "\n"; print FH "function ${agent_name}_driver::new(string name, uvm_component parent);\n"; print FH " super.new(name, parent);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; if ( exists $agent_driv_inc{$agent_name} && -e "${project}/tb/include/$agent_driv_inc{$agent_name}" ) { print FH "task " . $agent_name . "_driver::run_phase(uvm_phase phase);\n"; print FH " `uvm_info(get_type_name(), \"run_phase\", UVM_HIGH)\n"; print FH "\n"; print FH " forever\n"; print FH " begin\n"; print FH " seq_item_port.get_next_item(req);\n"; print FH " `uvm_info(get_type_name(), {\"req item\\n\",req.sprint}, UVM_HIGH)\n"; print FH " do_drive();\n"; print FH " seq_item_port.item_done();\n"; my $agent_clock = $agent_clock_array[0]; if ( not $agent_clock or $agent_clock eq "" ) { print FH " # 10ns;\n"; } print FH " end\n"; print FH "endtask : run_phase\n"; print FH "\n"; print FH "\n"; insert_inc_file("", $agent_driv_inc{$agent_name}, $agent_driv_inc_inline{$agent_name}, "", ""); } 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}); print FH "`endif // " . uc($agent_name) . "_DRIVER_SV\n"; print FH "\n"; close(FH); } sub gen_monitor { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_monitor.sv" ) || die "Exiting due to Error: can't open monitor: $agent_name"; write_file_header "${agent_name}_monitor.sv", "Monitor for $agent_name"; print FH "`ifndef " . uc($agent_name) . "_MONITOR_SV\n"; print FH "`define " . uc($agent_name) . "_MONITOR_SV\n"; print FH "\n"; 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}); print FH "class ${agent_name}_monitor extends uvm_monitor;\n"; print FH "\n"; print FH " `uvm_component_utils(" . $agent_name . "_monitor)\n"; print FH "\n"; my $interface_type; if ( $split_transactors eq "YES" ) { $interface_type = $agent_name . "_bfm"; } elsif ( exists $byo_interface{$agent_name} ) { $interface_type = $byo_interface{$agent_name}; } else { $interface_type = $agent_if; } print FH " virtual ${interface_type} vif;\n"; print FH "\n"; print FH " ${agent_name}_config m_config;\n"; print FH "\n"; print FH " uvm_analysis_port #(${agent_item}) analysis_port;\n"; print FH "\n"; if ( exists $agent_mon_inc{$agent_name} && -e "${project}/tb/include/$agent_mon_inc{$agent_name}" ) { print FH " ${agent_item} m_trans;\n"; print FH "\n"; } print FH " extern function new(string name, uvm_component parent);\n"; if ( exists $agent_mon_inc{$agent_name} && -e "${project}/tb/include/$agent_mon_inc{$agent_name}" ) { print FH "\n"; print FH " // Methods run_phase, and do_mon generated by setting monitor_inc in file $tpl_fname{$agent_name}\n"; print FH " extern task run_phase(uvm_phase phase);\n"; print FH " extern task do_mon();\n"; } print FH "\n"; 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}); print FH "endclass : " . $agent_name . "_monitor \n"; print FH "\n"; print FH "\n"; print FH "function ${agent_name}_monitor::new(string name, uvm_component parent);\n"; print FH " super.new(name, parent);\n"; print FH " analysis_port = new(\"analysis_port\", this);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; if ( exists $agent_mon_inc{$agent_name} && -e "${project}/tb/include/$agent_mon_inc{$agent_name}" ) { print FH "task ${agent_name}_monitor::run_phase(uvm_phase phase);\n"; print FH " `uvm_info(get_type_name(), \"run_phase\", UVM_HIGH)\n"; print FH "\n"; print FH " m_trans = ${agent_item}::type_id::create(\"m_trans\");\n"; print FH " do_mon();\n"; print FH "endtask : run_phase\n"; print FH "\n"; print FH "\n"; insert_inc_file("", $agent_mon_inc{$agent_name}, $agent_mon_inc_inline{$agent_name}, "", ""); } 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}); print FH "`endif // " . uc($agent_name) . "_MONITOR_SV\n"; print FH "\n"; close(FH); } sub gen_sequencer { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_sequencer.sv" ) || die "Exiting due to Error: can't open sequencer: $agent_name"; write_file_header "${agent_name}_sequencer.sv", "Sequencer for $agent_name"; print FH "`ifndef " . uc($agent_name) . "_SEQUENCER_SV\n"; print FH "`define " . uc($agent_name) . "_SEQUENCER_SV\n"; print FH "\n"; if ( $agent_seqr_class =~ /y|yes/i ) { 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}); print FH "class ${agent_name}_sequencer extends uvm_sequencer #(${agent_item});\n"; print FH "\n"; print FH " `uvm_component_utils(" . $agent_name . "_sequencer)\n"; print FH "\n"; print FH " extern function new(string name, uvm_component parent);\n"; print FH "\n"; 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}); print FH "endclass : " . $agent_name . "_sequencer \n"; print FH "\n"; print FH "\n"; print FH "function ${agent_name}_sequencer::new(string name, uvm_component parent);\n"; print FH " super.new(name, parent);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; 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}); print FH "\n"; print FH "typedef ${agent_name}_sequencer ${agent_name}_sequencer_t;\n"; } else { print FH "// Sequencer class is specialization of uvm_sequencer\n"; print FH "typedef uvm_sequencer #(" . $agent_item . ") " . $agent_name . "_sequencer_t;\n"; } print FH "\n"; print FH "\n"; print FH "`endif // " . uc($agent_name) . "_SEQUENCER_SV\n"; print FH "\n"; close(FH); } sub gen_config { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_config.sv" ) || die "Exiting due to Error: can't open config: $agent_name\n"; write_file_header "${agent_name}_config.sv", "Configuration for agent $agent_name"; print FH "`ifndef " . uc($agent_name) . "_CONFIG_SV\n"; print FH "`define " . uc($agent_name) . "_CONFIG_SV\n"; print FH "\n"; 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}); print FH "class ${agent_name}_config extends uvm_object;\n"; print FH "\n"; print FH " // Do not register config class with the factory\n"; print FH "\n"; my $interface_type; if ( $split_transactors eq "YES" ) { $interface_type = $agent_name . "_bfm"; } elsif ( exists $byo_interface{$agent_name} ) { $interface_type = $byo_interface{$agent_name}; } else { $interface_type = $agent_name . "_if"; } align(" virtual ${interface_type} ", "vif;\n ", ""); if ( exists $reg_access_mode{$agent_name} ) { align(" $reg_access_block_type{$agent_name} ", "regmodel;\n", ""); } align(" uvm_active_passive_enum ", "is_active = UVM_ACTIVE;", ""); align(" bit ", "coverage_enable;", ""); align(" bit ", "checks_enable;", ""); gen_aligned(); print FH "\n"; unless ( @config_var_array ) { print FH " // You can insert variables here by setting config_var in file $tpl_fname{$agent_name}\n"; } foreach my $var_decl (@config_var_array) { print FH " $var_decl\n"; } print FH "\n"; unless ( exists $agent_config_generate_methods_inside_class{$agent_name} && $agent_config_generate_methods_inside_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH " // You can remove new by setting agent_config_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n"; } print FH " extern function new(string name = \"\");\n"; print FH "\n"; } 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}); print FH "endclass : " . $agent_name . "_config \n"; print FH "\n"; print FH "\n"; unless ( exists $agent_config_generate_methods_after_class{$agent_name} && $agent_config_generate_methods_after_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH "// You can remove new by setting agent_config_generate_methods_after_class = no in file $tpl_fname{$agent_name}\n\n"; } print FH "function ${agent_name}_config::new(string name = \"\");\n"; print FH " super.new(name);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; } 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}); print FH "`endif // " . uc($agent_name) . "_CONFIG_SV\n"; print FH "\n"; close(FH); } sub gen_cov { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_coverage.sv" ) || die "Exiting due to Error: can't open coverage: $agent_name"; write_file_header "${agent_name}_coverage.sv", "Coverage for agent $agent_name"; print FH "`ifndef " . uc($agent_name) . "_COVERAGE_SV\n"; print FH "`define " . uc($agent_name) . "_COVERAGE_SV\n"; print FH "\n"; 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}); print FH "class ${agent_name}_coverage extends uvm_subscriber #(${agent_item});\n"; print FH "\n"; print FH " `uvm_component_utils(" . $agent_name . "_coverage)\n"; print FH "\n"; align(" ${agent_name}_config ", "m_config;", ""); align(" bit ", "m_is_covered;", ""); align(" $agent_item ", "m_item;\n", ""); gen_aligned(); #if include file for coverage collector exists, pull it in here, otherwise #create covergroup and coverpoints with default bins if ( exists $agent_cover_inc{$agent_name} && -e "${project}/tb/include/$agent_cover_inc{$agent_name}" ) { open(FH_COV, "<${project}/tb/include/$agent_cover_inc{$agent_name}") or die "CANNOT OPEN INCLUDE FILE agent_cover_inc{$agent_name}"; my $cov_inc = join("",<FH_COV>); #check that file contains covergroup named "m_cov" unless ($cov_inc =~ /covergroup\s+m_cov(\s|;)/) { warning_prompt("COVERGROUP \"m_cov\" MUST BE DEFINED IN $agent_cover_inc{$agent_name}"); } insert_inc_file(" ", $agent_cover_inc{$agent_name}, $agent_cover_inc_inline{$agent_name}, "", ""); } else { unless ( exists $agent_cover_generate_methods_inside_class{$agent_name} && $agent_cover_generate_methods_inside_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH " // You can replace covergroup m_cov by setting agent_cover_inc in file $tpl_fname{$agent_name}\n"; print FH " // or remove covergroup m_cov by setting agent_cover_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n"; } print FH " covergroup m_cov;\n"; print FH " option.per_instance = 1;\n"; print FH " // You may insert additional coverpoints here ...\n"; print FH "\n"; foreach $field ( @non_local_tx_vars ) { # print FH " cp_${i}: coverpoint m_item.${tmp};\n"; print FH " cp_${field}: coverpoint m_item.${field};\n"; print FH " // Add bins here if required\n"; print FH "\n"; } print FH " endgroup\n"; print FH "\n"; } } unless ( exists $agent_cover_generate_methods_inside_class{$agent_name} && $agent_cover_generate_methods_inside_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH " extern function new(string name, uvm_component parent);\n"; print FH " extern function void write(input " . $agent_item . " t);\n"; print FH " extern function void build_phase(uvm_phase phase);\n"; print FH " extern function void report_phase(uvm_phase phase);\n"; print FH "\n"; } 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}); print FH "endclass : " . $agent_name . "_coverage \n"; print FH "\n"; print FH "\n"; unless ( exists $agent_cover_generate_methods_after_class{$agent_name} && $agent_cover_generate_methods_after_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH "function ${agent_name}_coverage::new(string name, uvm_component parent);\n"; print FH " super.new(name, parent);\n"; print FH " m_is_covered = 0;\n"; print FH " m_cov = new();\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_name}_coverage::write(input ${agent_item} t);\n"; print FH " if (m_config.coverage_enable)\n"; print FH " begin\n"; print FH " m_item = t;\n"; print FH " m_cov.sample();\n"; print FH " // Check coverage - could use m_cov.option.goal instead of 100 if your simulator supports it\n"; print FH " if (m_cov.get_inst_coverage() >= 100) m_is_covered = 1;\n"; print FH " end\n"; print FH "endfunction : write\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_name}_coverage::build_phase(uvm_phase phase);\n"; print FH " if (!uvm_config_db #(${agent_name}_config)::get(this, \"\", \"config\", m_config))\n"; print FH " `uvm_error(get_type_name(), \"${agent_name} config not found\")\n"; print FH "endfunction : build_phase\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_name}_coverage::report_phase(uvm_phase phase);\n"; print FH " if (m_config.coverage_enable)\n"; print FH " `uvm_info(get_type_name(), \$sformatf(\"Coverage score = %3.1f%%\", m_cov.get_inst_coverage()), UVM_MEDIUM)\n"; print FH " else\n"; print FH " `uvm_info(get_type_name(), \"Coverage disabled for this agent\", UVM_MEDIUM)\n"; print FH "endfunction : report_phase\n"; print FH "\n"; print FH "\n"; } 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}); print FH "`endif // " . uc($agent_name) . "_COVERAGE_SV\n"; print FH "\n"; close(FH); } sub gen_agent { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_agent.sv" ) || die "Exiting due to Error: can't open agent: $agent_name"; write_file_header "${agent_name}_agent.sv", "Agent for $agent_name"; print FH "`ifndef " . uc($agent_name) . "_AGENT_SV\n"; print FH "`define " . uc($agent_name) . "_AGENT_SV\n"; print FH "\n"; insert_inc_file("", $agent_inc_before_class{$agent_name}, $agent_inc_before_inline{$agent_name}, "agent_inc_before_class", $tpl_fname{$agent_name}); print FH "class ${agent_name}_agent extends uvm_agent;\n"; print FH "\n"; print FH " `uvm_component_utils(${agent_name}_agent)\n"; print FH "\n"; print FH " uvm_analysis_port #(${agent_item}) analysis_port;\n"; print FH "\n"; print FH " ${agent_name}_config m_config;\n"; print FH " ${agent_name}_sequencer_t m_sequencer;\n"; print FH " ${agent_name}_driver m_driver;\n"; print FH " ${agent_name}_monitor m_monitor;\n"; print FH "\n"; print FH " local int m_is_active = -1;\n"; print FH "\n"; print FH " extern function new(string name, uvm_component parent);\n"; print FH "\n"; unless ( exists $agent_generate_methods_inside_class{$agent_name} && $agent_generate_methods_inside_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH " extern function void build_phase(uvm_phase phase);\n"; print FH " extern function void connect_phase(uvm_phase phase);\n"; print FH " extern function uvm_active_passive_enum get_is_active();\n"; print FH "\n"; } insert_inc_file(" ", $agent_inc_inside_class{$agent_name}, $agent_inc_inside_inline{$agent_name}, "agent_inc_inside_class", $tpl_fname{$agent_name}); print FH "endclass : " . $agent_name . "_agent \n"; print FH "\n"; print FH "\n"; print FH "function ${agent_name}_agent::new(string name, uvm_component parent);\n"; print FH " super.new(name, parent);\n"; print FH " analysis_port = new(\"analysis_port\", this);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; unless ( exists $agent_generate_methods_after_class{$agent_name} && $agent_generate_methods_after_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH "function void ${agent_name}_agent::build_phase(uvm_phase phase);\n"; print FH "\n"; 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}); print FH " if (!uvm_config_db #(${agent_name}_config)::get(this, \"\", \"config\", m_config))\n"; print FH " `uvm_error(get_type_name(), \"${agent_name} config not found\")\n"; print FH "\n"; print FH " m_monitor = ${agent_name}_monitor ::type_id::create(\"m_monitor\", this);\n"; print FH "\n"; print FH " if (get_is_active() == UVM_ACTIVE)\n"; print FH " begin\n"; print FH " m_driver = ${agent_name}_driver ::type_id::create(\"m_driver\", this);\n"; print FH " m_sequencer = ${agent_name}_sequencer_t::type_id::create(\"m_sequencer\", this);\n"; print FH " end\n"; print FH "\n"; 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}); print FH "endfunction : build_phase\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_name}_agent::connect_phase(uvm_phase phase);\n"; print FH " if (m_config.vif == null)\n"; print FH " `uvm_warning(get_type_name(), \"${agent_name} virtual interface is not set!\")\n"; print FH "\n"; print FH " m_monitor.vif = m_config.vif;\n"; print FH " m_monitor.m_config = m_config;\n"; print FH " m_monitor.analysis_port.connect(analysis_port);\n"; print FH "\n"; print FH " if (get_is_active() == UVM_ACTIVE)\n"; print FH " begin\n"; print FH " m_driver.seq_item_port.connect(m_sequencer.seq_item_export);\n"; print FH " m_driver.vif = m_config.vif;\n"; print FH " m_driver.m_config = m_config;\n"; print FH " end\n"; print FH "\n"; 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}); print FH "endfunction : connect_phase\n"; print FH "\n"; print FH "\n"; print FH "function uvm_active_passive_enum ${agent_name}_agent::get_is_active();\n"; print FH " if (m_is_active == -1)\n"; print FH " begin\n"; print FH " if (uvm_config_db#(uvm_bitstream_t)::get(this, \"\", \"is_active\", m_is_active))\n"; print FH " begin\n"; print FH " if (m_is_active != m_config.is_active)\n"; print FH " `uvm_warning(get_type_name(), \"is_active field in config_db conflicts with config object\")\n"; print FH " end\n"; print FH " else \n"; print FH " m_is_active = m_config.is_active;\n"; print FH " end\n"; print FH " return uvm_active_passive_enum'(m_is_active);\n"; print FH "endfunction : get_is_active\n"; print FH "\n"; print FH "\n"; } insert_inc_file("", $agent_inc_after_class{$agent_name}, $agent_inc_after_inline{$agent_name}, "agent_inc_after_class", $tpl_fname{$agent_name}); print FH "`endif // " . uc($agent_name) . "_AGENT_SV\n"; print FH "\n"; close(FH); } sub gen_env { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_env.sv" ) || die "Exiting due to Error: can't open env: $agent_name"; write_file_header "${agent_name}_env.sv", "Environment for agent $agent_name"; print FH "`ifndef " . uc($agent_name) . "_ENV_SV\n"; print FH "`define " . uc($agent_name) . "_ENV_SV\n"; print FH "\n"; 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}); print FH "class ${agent_name}_env extends uvm_env;\n"; print FH "\n"; print FH " `uvm_component_utils(" . $agent_name . "_env)\n"; print FH "\n"; print FH " extern function new(string name, uvm_component parent);\n"; print FH "\n"; for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent_name}); align(" ${agent_name}_config ", "m_${agent_name}${suffix}_config;", ""); align(" ${agent_name}_agent ", "m_${agent_name}${suffix}_agent;", ""); align(" ${agent_name}_coverage ", "m_${agent_name}${suffix}_coverage;", ""); if ( exists $reg_access_mode{$agent_name} ) { align(" ${agent_name}_env_coverage ", "m_${agent_name}${suffix}_env_coverage;", ""); align(" $reg_access_block_type{$agent_name} ", "regmodel${suffix}; // Register model", ""); align("\n", "", ""); align(" reg2${agent_name}_adapter ", "m_reg2${agent_name}${suffix};", ""); align(" uvm_reg_predictor #($agent_item_types{$agent_name}) ", "m_${agent_name}2reg_predictor${suffix};", ""); } align("\n", "", ""); } gen_aligned(); #add any other agents (%env_agents is hash of ref to array) do { foreach my $extra_agent ( @{ $env_agents{"${agent_name}_env"} } ) { print LOGFILE "adding extra agent $extra_agent\n"; print FH " ${extra_agent}_config m_${extra_agent}_config;\n"; print FH " ${extra_agent}_agent m_${extra_agent}_agent;\n"; print FH " ${extra_agent}_coverage m_${extra_agent}_coverage;\n"; print FH "\n"; } } if exists $env_agents{"${agent_name}_env"}; unless ( exists $agent_env_generate_methods_inside_class{$agent_name} && $agent_env_generate_methods_inside_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH " extern function void build_phase(uvm_phase phase);\n"; print FH " extern function void connect_phase(uvm_phase phase);\n"; print FH "\n"; } 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}); print FH "endclass : " . $agent_name . "_env \n"; print FH "\n"; print FH "\n"; print FH "function ${agent_name}_env::new(string name, uvm_component parent);\n"; print FH " super.new(name, parent);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; unless ( exists $agent_env_generate_methods_after_class{$agent_name} && $agent_env_generate_methods_after_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH "function void ${agent_name}_env::build_phase(uvm_phase phase);\n"; print FH "\n"; 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}); for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent_name}); if ($i > 0) { print FH "\n"; } print FH " if (!uvm_config_db #(${agent_name}_config)::get(this, \"\", \"config${suffix}\", m_${agent_name}${suffix}_config))\n"; print FH " `uvm_error(get_type_name(), \"Unable to get config from configuration database\")\n"; print FH " regmodel${suffix} = m_${agent_name}${suffix}_config.regmodel;\n" if exists $reg_access_mode{$agent_name}; print FH "\n"; print FH " uvm_config_db #(${agent_name}_config)::set(this, \"m_${agent_name}${suffix}_agent\", \"config\", m_${agent_name}${suffix}_config);\n"; print FH " if (m_${agent_name}${suffix}_config.is_active == UVM_ACTIVE )\n"; print FH " uvm_config_db #(${agent_name}_config)::set(this, \"m_${agent_name}${suffix}_agent.m_sequencer\", \"config\", m_${agent_name}${suffix}_config);\n"; print FH " uvm_config_db #(${agent_name}_config)::set(this, \"m_${agent_name}${suffix}_coverage\", \"config\", m_${agent_name}${suffix}_config);\n"; if ( exists $reg_access_mode{$agent_name} ) { print FH " uvm_config_db #(${agent_name}_config)::set(this, \"m_${agent_name}${suffix}_env_coverage\", \"config\", m_${agent_name}${suffix}_config);\n"; } print FH "\n"; print FH " m_${agent_name}${suffix}_agent = ${agent_name}_agent ::type_id::create(\"m_${agent_name}${suffix}_agent\", this);\n"; print FH "\n"; print FH " m_${agent_name}${suffix}_coverage = ${agent_name}_coverage::type_id::create(\"m_${agent_name}${suffix}_coverage\", this);\n"; if ( exists $reg_access_mode{$agent_name} ) { print FH " m_${agent_name}${suffix}_env_coverage = ${agent_name}_env_coverage::type_id::create(\"m_${agent_name}${suffix}_env_coverage\", this);\n"; print FH " m_reg2${agent_name}${suffix} = reg2${agent_name}_adapter ::type_id::create(\"m_reg2${agent_name}${suffix}\", this);\n"; print FH "\n"; print FH " m_${agent_name}2reg_predictor${suffix} = "; print FH "uvm_reg_predictor #($agent_item_types{$agent_name})::type_id::create(\"m_${agent_name}2reg_predictor${suffix}\", this);\n"; } } do { print FH "\n"; print FH " // Additional agents"; foreach my $extra_agent ( @{ $env_agents{"${agent_name}_env"} } ) { print FH "\n"; print FH " if (!uvm_config_db #(${extra_agent}_config)::get(this, \"\", \"config\", m_${extra_agent}_config))\n"; print FH " `uvm_error(get_type_name(), \"Unable to get ${extra_agent}_config from configuration database\")\n"; print FH "\n"; print FH " uvm_config_db #(${extra_agent}_config)::set(this, \"m_${extra_agent}_agent\", \"config\", m_${extra_agent}_config);\n"; print FH " if (m_${extra_agent}_config.is_active == UVM_ACTIVE )\n"; print FH " uvm_config_db #(${extra_agent}_config)::set(this, \"m_${extra_agent}_agent.m_sequencer\", \"config\", m_${extra_agent}_config);\n"; print FH " uvm_config_db #(${extra_agent}_config)::set(this, \"m_${extra_agent}_coverage\", \"config\", m_${extra_agent}_config);\n"; print FH "\n"; print FH " m_${extra_agent}_agent = ${extra_agent}_agent ::type_id::create(\"m_${extra_agent}_agent\", this);\n"; print FH " m_${extra_agent}_coverage = ${extra_agent}_coverage::type_id::create(\"m_${extra_agent}_coverage\", this);\n"; } } if exists $env_agents{"${agent_name}_env"}; print FH "\n"; 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}); print FH "endfunction : build_phase\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_name}_env::connect_phase(uvm_phase phase);\n"; print FH "\n"; for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent_name}); align(" m_${agent_name}${suffix}_agent", ".analysis_port.connect(m_${agent_name}${suffix}_coverage.analysis_export);\n", ""); if ( exists $reg_access_mode{$agent_name} ) { align(" m_${agent_name}${suffix}_agent", ".analysis_port.connect(m_${agent_name}2reg_predictor${suffix}.bus_in);\n", ""); align(" m_${agent_name}${suffix}_agent", ".analysis_port.connect(m_${agent_name}${suffix}_env_coverage.analysis_export);\n", ""); align(" m_${agent_name}${suffix}_env_coverage.regmodel = regmodel${suffix};\n", "", ""); } } do { foreach my $extra_agent ( @{ $env_agents{"${agent_name}_env"} } ) { align(" m_${extra_agent}_agent", ".analysis_port.connect(m_${extra_agent}_coverage.analysis_export);", ""); } } if exists $env_agents{"${agent_name}_env"}; gen_aligned(); print FH "\n"; 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}); print FH "endfunction : connect_phase\n"; print FH "\n"; print FH "\n"; } 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}); print FH "`endif // " . uc($agent_name) . "_ENV_SV\n"; print FH "\n"; close(FH); } sub gen_seq_lib { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_seq_lib.sv" ) || die "Exiting due to Error: can't open seq_lib: $agent_name"; write_file_header "${agent_name}_seq_lib.sv", "Sequence for agent $agent_name"; print FH "`ifndef " . uc($agent_name) . "_SEQ_LIB_SV\n"; print FH "`define " . uc($agent_name) . "_SEQ_LIB_SV\n"; print FH "\n"; print FH "class ${agent_name}_default_seq extends uvm_sequence #($agent_item);\n"; print FH "\n"; print FH " `uvm_object_utils(" . $agent_name . "_default_seq)\n"; print FH "\n"; print FH " ${agent_name}_config m_config;\n"; print FH "\n"; print FH " extern function new(string name = \"\");\n"; print FH " extern task body();\n"; print FH "\n"; print FH "`ifndef UVM_POST_VERSION_1_1\n"; print FH " // Functions to support UVM 1.2 objection API in UVM 1.1\n"; print FH " extern function uvm_phase get_starting_phase();\n"; print FH " extern function void set_starting_phase(uvm_phase phase);\n"; print FH "`endif\n"; print FH "\n"; print FH "endclass : " . $agent_name . "_default_seq\n"; print FH "\n"; print FH "\n"; print FH "function ${agent_name}_default_seq::new(string name = \"\");\n"; print FH " super.new(name);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; print FH "task ${agent_name}_default_seq::body();\n"; print FH " `uvm_info(get_type_name(), \"Default sequence starting\", UVM_HIGH)\n"; print FH "\n"; print FH " req = " . $agent_item . "::type_id::create(\"req\");\n"; print FH " start_item(req); \n"; print FH " if ( !req.randomize() )\n"; print FH " `uvm_error(get_type_name(), \"Failed to randomize transaction\")\n"; print FH " finish_item(req); \n"; print FH "\n"; print FH " `uvm_info(get_type_name(), \"Default sequence completed\", UVM_HIGH)\n"; print FH "endtask : body\n"; print FH "\n"; print FH "\n"; print FH "`ifndef UVM_POST_VERSION_1_1\n"; print FH "function uvm_phase ${agent_name}_default_seq::get_starting_phase();\n"; print FH " return starting_phase;\n"; print FH "endfunction: get_starting_phase\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_name}_default_seq::set_starting_phase(uvm_phase phase);\n"; print FH " starting_phase = phase;\n"; print FH "endfunction: set_starting_phase\n"; print FH "`endif\n"; print FH "\n"; print FH "\n"; insert_inc_file("", $agent_seq_inc{$agent_name}, $agent_seq_inc_inline{$agent_name}, "agent_seq_inc", $tpl_fname{$agent_name}); print FH "`endif // " . uc($agent_name) . "_SEQ_LIB_SV\n"; print FH "\n"; close(FH); } sub gen_env_seq_lib { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_env_seq_lib.sv" ) || die "Exiting due to Error: can't open env_seq_lib: $agent_name"; write_file_header "${agent_name}_env_seq_lib.sv", "Sequence for $agent_name"; print FH "`ifndef " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n"; print FH "`define " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n"; print FH "\n"; print FH "class ${agent_name}_env_default_seq extends uvm_sequence #(uvm_sequence_item);\n"; print FH "\n"; print FH " `uvm_object_utils(" . $agent_name . "_env_default_seq)\n"; print FH "\n"; print FH " ${agent_name}_env m_env;\n"; print FH "\n"; print FH " extern function new(string name = \"\");\n"; print FH " extern task body();\n"; print FH "\n"; print FH "`ifndef UVM_POST_VERSION_1_1\n"; print FH " // Functions to support UVM 1.2 objection API in UVM 1.1\n"; print FH " extern function uvm_phase get_starting_phase();\n"; print FH " extern function void set_starting_phase(uvm_phase phase);\n"; print FH "`endif\n"; print FH "\n"; print FH "endclass : " . $agent_name . "_env_default_seq\n"; print FH "\n"; print FH "\n"; print FH "function ${agent_name}_env_default_seq::new(string name = \"\");\n"; print FH " super.new(name);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; print FH "task ${agent_name}_env_default_seq::body();\n"; print FH " `uvm_info(get_type_name(), \"Default sequence starting\", UVM_HIGH)\n"; print FH "\n"; print FH " // Note: there can be multiple child sequences started concurrently within this fork..join\n"; print FH " fork\n"; for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent_name}); my $sequencer_instance_name = "m_env.m_${agent_name}${suffix}_agent.m_sequencer"; if ( $i > 0 ) { print FH "\n"; } print FH " if (m_env.m_${agent_name}${suffix}_config.is_active == UVM_ACTIVE)\n"; print FH " begin\n"; print FH " ${agent_name}_default_seq seq;\n"; print FH " seq = ${agent_name}_default_seq::type_id::create(\"seq${suffix}\");\n"; print FH " seq.set_item_context(this, ${sequencer_instance_name});\n"; print FH " if ( !seq.randomize() )\n"; print FH " `uvm_error(get_type_name(), \"Failed to randomize sequence\")\n"; print FH " seq.m_config = m_env.m_${agent_name}${suffix}_config;\n"; print FH " seq.set_starting_phase( get_starting_phase() );\n"; print FH " seq.start(${sequencer_instance_name}, this);\n"; print FH " end\n"; } foreach my $extra_agent ( @{ $env_agents{"${agent_name}_env"} } ) { my $sequencer_instance_name = "m_env.m_${extra_agent}_agent.m_sequencer"; print FH "\n"; print FH " if (m_env.m_${extra_agent}_agent.m_config.is_active == UVM_ACTIVE)\n"; print FH " begin\n"; print FH " ${extra_agent}_default_seq seq;\n"; print FH " seq = ${extra_agent}_default_seq::type_id::create(\"seq\");\n"; print FH " seq.set_item_context(this, ${sequencer_instance_name});\n"; print FH " if ( !seq.randomize() )\n"; print FH " `uvm_error(get_type_name(), \"Failed to randomize sequence\")\n"; print FH " seq.m_config = m_env.m_${extra_agent}_agent.m_config;\n"; print FH " seq.set_starting_phase( get_starting_phase() );\n"; print FH " seq.start(${sequencer_instance_name}, this);\n"; print FH " end\n"; } print FH " join\n"; print FH "\n"; print FH " `uvm_info(get_type_name(), \"Default sequence completed\", UVM_HIGH)\n"; print FH "endtask : body\n"; print FH "\n"; print FH "\n"; print FH "`ifndef UVM_POST_VERSION_1_1\n"; print FH "function uvm_phase ${agent_name}_env_default_seq::get_starting_phase();\n"; print FH " return starting_phase;\n"; print FH "endfunction: get_starting_phase\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_name}_env_default_seq::set_starting_phase(uvm_phase phase);\n"; print FH " starting_phase = phase;\n"; print FH "endfunction: set_starting_phase\n"; print FH "`endif\n"; print FH "\n"; print FH "\n"; insert_inc_file("", $agent_env_seq_inc{$agent_name}, $agent_env_seq_inc_inline{$agent_name}, "agent_env_seq_inc", $tpl_fname{$agent_name}); print FH "`endif // " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n"; print FH "\n"; close(FH); } sub gen_agent_pkg { ### file list for files in sv directoru (.svh file) $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_pkg.sv" ) || die "Exiting due to Error: can't open include file: $agent_name"; write_file_header "${agent_name}_pkg.sv", "Package for agent $agent_name"; print FH "package ${agent_name}_pkg;\n"; print FH "\n"; print FH " `include \"uvm_macros.svh\"\n"; print FH "\n"; print FH " import uvm_pkg::*;\n"; print FH "\n"; print FH " import ${common_pkg}::*;\n" if $common_pkg; print FH " import ${common_env_pkg}::*;\n" if $common_env_pkg; print FH " import regmodel_pkg::*;\n" if exists $reg_access_mode{$agent_name}; do { foreach my $extra_agent ( @{ $env_agents{"${agent_name}_env"} } ) { print FH " import ${extra_agent}_pkg::*;\n"; } } if exists $env_agents{"${agent_name}_env"}; print FH "\n"; print FH " `include \"${agent_name}_${agent_item}.sv\"\n"; print FH " `include \"" . $agent_name . "_config.sv\"\n"; print FH " `include \"" . $agent_name . "_driver.sv\"\n"; print FH " `include \"" . $agent_name . "_monitor.sv\"\n"; print FH " `include \"" . $agent_name . "_sequencer.sv\"\n"; print FH " `include \"" . $agent_name . "_coverage.sv\"\n"; print FH " `include \"" . $agent_name . "_agent.sv\"\n"; print FH " `include \"" . $agent_name . "_seq_lib.sv\"\n"; if ( exists $reg_access_mode{$agent_name} ) { print FH " `include \"reg2" . $agent_name . "_adapter.sv\"\n"; print FH " `include \"" . $agent_name . "_env_coverage.sv\"\n"; } do { print FH " `include \"" . $agent_name . "_env.sv\"\n"; print FH " `include \"" . $agent_name . "_env_seq_lib.sv\"\n"; } unless $agent_has_env eq "NO"; print FH "\n"; print FH "endpackage : ${agent_name}_pkg\n"; close(FH); } sub gen_top_pkg { ### file list for files in sv directoru (.svh file) $dir = $project . "/tb/" . $tbname; open( FH, ">" . $dir . "/sv/" . $tbname . "_pkg.sv" ) || die "Exiting due to Error: can't open include file: $tbname"; write_file_header "${tbname}_pkg.sv", "Package for $tbname"; print FH "package " . $tbname . "_pkg;\n"; print FH "\n"; print FH " `include \"uvm_macros.svh\"\n"; print FH "\n"; print FH " import uvm_pkg::*;\n"; print FH "\n"; print FH " import regmodel_pkg::*;\n" if $regmodel; print FH " import ${common_pkg}::*;\n" if $common_pkg; print FH " import ${common_env_pkg}::*;\n" if $common_env_pkg; foreach my $agent (@agent_list) { print FH " import ${agent}_pkg::*;\n"; } print FH "\n"; print FH " `include \"" . $tbname . "_config.sv\"\n"; print FH " `include \"" . $tbname . "_seq_lib.sv\"\n"; if ( keys %ref_model ) { print FH " `include \"port_converter.sv\"\n"; } foreach my $ref_model_name ( keys(%ref_model) ) { print FH " `include \"$ref_model_name.sv\"\n"; } print FH " `include \"" . $tbname . "_env.sv\"\n"; print FH "\n"; print FH "endpackage : " . $tbname . "_pkg\n"; print FH "\n"; close(FH); } sub gen_dut_inst() { my $port_list_file = $dut_pfile; open( PFH, $port_list_file ) or die "Exiting due to Error: can't open template: ${port_list_file}\n"; #skip empty lines my $line = ""; SKIP_BL: while (<PFH>) { if (/\w+/) { $line = $_; last SKIP_BL; } } $line or die "Exiting due to Error: dut_pfile $dut_pfile exists but is empty\n"; my $if_name = $1; my @param_list1; my @param_list2; my @param_list3; my @port_list1; my @port_list2; my @port_list3; my $count_of_trailing_comments = 0; XPROC_INTF: while ($line) { if ($if_name) { # The name in the pinlist file was originally an interface name but can now be a user-defined interface instance name instead if ( exists $if_instance_names{$if_name} ) { $if_name = $if_instance_names{$if_name}; } print LOGFILE "Writing ports for interface $if_name\n"; } while ($line) { if ( $line =~ m/\s*#/ ) { #script comments - ignore $line = <PFH>; next XPROC_INTF; } elsif ( $line =~ m!^\s*//.*\n! ) { #SV comments push @port_list1, " $&"; push @port_list2, ""; $count_of_trailing_comments++; } elsif ( $line =~ m/^\s*PAR\s*(\||\=)\s*(\S+)\s+(\S+)\n/ ) { #parameters push @param_list1, " .$2"; push @param_list2, "($3),"; } elsif ( $line =~ /^\s*(\S+)\s+(\S+)\s*\n/ ) { #ports if ($if_name) { push @port_list1, " .$1"; push @port_list2, "($if_name.$2),"; } else { push @port_list1, " .$1"; push @port_list2, "($2),"; } $count_of_trailing_comments = 0; } elsif ( $line =~ /\s*DEC\s*(\||\=)\s*(.+)\s*\n/ ) { #variable dec print FH " $2\n"; } elsif ( $line =~ /!(\w+){0,1}/ ) { #next if_name $if_name = ( $1 and $1 ne "none" ) ? $1 : ""; $line = <PFH>; next XPROC_INTF; } $line = <PFH>; } } #XPROC_INTF print FH " $dut_top "; if (@param_list1) { chop($param_list2[-1]); #remove trailing ',' print FH "#(\n"; pretty_print(\@param_list1, \@param_list2, \@param_list3); print FH " )\n "; } print FH "${dut_iname} (\n"; if (@port_list2) { chop($port_list2[-1-$count_of_trailing_comments]); } #remove trailing ',' pretty_print(\@port_list1, \@port_list2, \@port_list3); print FH " );\n"; } sub gen_top_env { $dir = $project . "/tb/" . $tbname; open( FH, ">" . $dir . "/sv/" . $tbname . "_env.sv" ) || die "Exiting due to Error: can't open env: $tbname"; write_file_header "${tbname}_env.sv", "Environment for $tbname"; print FH "`ifndef " . uc($tbname) . "_ENV_SV\n"; print FH "`define " . uc($tbname) . "_ENV_SV\n"; print FH "\n"; insert_inc_file("", $top_env_inc_before_class, $top_env_inc_before_inline, "top_env_inc_before_class", $common_tpl_fname); if ( keys %ref_model ) { print FH "import pk_syoscb::*;\n"; print FH "\n"; } print FH "class ${tbname}_env extends uvm_env;\n"; print FH "\n"; print FH " `uvm_component_utils(" . $tbname . "_env)\n"; print FH "\n"; print FH " extern function new(string name, uvm_component parent);\n"; print FH "\n"; if ( keys %ref_model ) { print FH " // Reference model and Syosil scoreboard\n"; } foreach my $ref_model_name ( keys(%ref_model) ) { #foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) { # $agent_name = ${agent_type_by_inst{$input}}; # my $name = $input; # $name =~ s/\./__/g; # align(" typedef port_converter #($agent_item_types{$agent_name}) ", "converter_${name}_t;", ""); #} foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) { $agent_name = ${agent_type_by_inst{$output}}; my $name = $output; $name =~ s/\./__/g; align(" typedef port_converter #($agent_item_types{$agent_name}) ", "converter_${name}_t;", ""); } } gen_aligned(); print FH "\n"; foreach my $ref_model_name ( keys(%ref_model) ) { #foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) { # my $name = $input; # $name =~ s/\./__/g; # align(" converter_${name}_t ", "m_converter_${name};", ""); #} foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) { my $name = $output; $name =~ s/\./__/g; align(" converter_${name}_t ", "m_converter_${name};", ""); } align("\n", "", ""); align(" $ref_model_name ", "m_${ref_model_name};", ""); align(" cl_syoscb ", "m_${ref_model_name}_scoreboard;", ""); align(" cl_syoscb_cfg ", "m_${ref_model_name}_config;", ""); align("\n", "", ""); } gen_aligned(); print FH " // Child environments\n" if @env_list; foreach my $agent_env (@env_list) { align(" ${agent_env} ", "m_${agent_env};", ""); } align("\n", "", "") if @env_list; foreach my $agent (@agent_list) { for ( my $i = 0 ; $i < $number_of_instances{$agent} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent}); do { align(" ${agent}_config ", "m_${agent}${suffix}_config;", ""); } unless grep( /$agent/, @top_env_agents ); } } align("\n", "", "") if @env_list; align(" // Child agents\n", "", "") if @top_env_agents; foreach $aname (@top_env_agents) { for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$aname}); align(" ${aname}_config ", "m_${aname}${suffix}_config;", ""); align(" ${aname}_agent ", "m_${aname}${suffix}_agent;", ""); align(" ${aname}_coverage ", "m_${aname}${suffix}_coverage;", ""); align("\n", "", ""); } } if ( $regmodel ) { align(" // Register model\n", "", ""); align(" $top_reg_block_type ", "regmodel;", ""); } align(" ${tbname}_config ", "m_config;\n", ""); gen_aligned(); unless ( defined $top_env_generate_methods_inside_class && $top_env_generate_methods_inside_class eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH " extern function void build_phase(uvm_phase phase);\n"; print FH " extern function void connect_phase(uvm_phase phase);\n"; unless ( defined $top_env_generate_end_of_elaboration && $top_env_generate_end_of_elaboration eq "NO" ) { print FH " extern function void end_of_elaboration_phase(uvm_phase phase);\n"; } unless ( defined $top_env_generate_run_phase && $top_env_generate_run_phase eq "NO" ) { print FH " extern task run_phase(uvm_phase phase);\n"; } print FH "\n"; } insert_inc_file(" ", $top_env_inc_inside_class, $top_env_inc_inside_inline, "top_env_inc_inside_class", $common_tpl_fname); print FH "endclass : " . $tbname . "_env \n"; print FH "\n"; print FH "\n"; print FH "function ${tbname}_env::new(string name, uvm_component parent);\n"; print FH " super.new(name, parent);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; unless ( defined $top_env_generate_methods_after_class && $top_env_generate_methods_after_class eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH "function void ${tbname}_env::build_phase(uvm_phase phase);\n"; print FH " `uvm_info(get_type_name(), \"In build_phase\", UVM_HIGH)\n"; print FH "\n"; 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); print FH " if (!uvm_config_db #(${tbname}_config)::get(this, \"\", \"config\", m_config)) \n"; print FH " `uvm_error(get_type_name(), \"Unable to get ${tbname}_config\")\n"; do { print FH "\n"; print FH " regmodel = ${top_reg_block_type}::type_id::create(\"regmodel\");\n"; print FH " regmodel.build();\n"; } if $regmodel; foreach my $agent (@agent_list) { for ( my $i = 0 ; $i < $number_of_instances{$agent} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent}); align("\n", "", ""); if ( defined $nested_config_objects && $nested_config_objects eq "YES" ) { align(" m_${agent}${suffix}_config ", "= m_config.m_${agent}${suffix}_config;", ""); } else { align(" m_${agent}${suffix}_config ", "= new(\"m_${agent}${suffix}_config\");", ""); align(" m_${agent}${suffix}_config.vif ", "= m_config.${agent}${suffix}_vif;", ""); align(" m_${agent}${suffix}_config.is_active ", "= m_config.is_active_${agent}${suffix};", ""); } if ( exists $reg_access_mode{$agent} ) { my $value; if ( ${reg_access_instance{$agent}} ne "" ) { $value = "regmodel${reg_access_instance{$agent}}${suffix}"; } else { $value = "regmodel"; } align(" m_${agent}${suffix}_config.regmodel ", "= ${value};", ""); } unless ( defined $nested_config_objects && $nested_config_objects eq "YES" ) { align(" m_${agent}${suffix}_config.checks_enable ", "= m_config.checks_enable_${agent}${suffix};", ""); align(" m_${agent}${suffix}_config.coverage_enable ", "= m_config.coverage_enable_${agent}${suffix};", ""); } gen_aligned(); } print FH "\n"; insert_inc_file(" ", $agent_copy_config_vars{$agent}, $agent_copy_config_vars_inline{$agent}, "agent_copy_config_vars", $tpl_fname{$agent}); for ( my $i = 0 ; $i < $number_of_instances{$agent} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent}); if ( grep( /$agent/, @stand_alone_agents ) ) { # agent_has_env = no if ( grep( /$agent/, @top_env_agents ) ) { # Agent instantiated at top level. Need to set config for agent align(" uvm_config_db #(${agent}_config)::set(this, \"m_${agent}${suffix}_agent\", \"config\", m_${agent}${suffix}_config);\n", "", ""); align(" if (m_${agent}${suffix}_config.is_active == UVM_ACTIVE )\n", "", ""); align(" uvm_config_db #(${agent}_config)::set(this, \"m_${agent}${suffix}_agent.m_sequencer\", \"config\", m_${agent}${suffix}_config);\n", "", ""); align(" uvm_config_db #(${agent}_config)::set(this, \"m_${agent}${suffix}_coverage\", \"config\", m_${agent}${suffix}_config);\n", "", ""); } else { # additional_agent. Need to set config for env that contains agent align(" uvm_config_db #(${agent}_config)::set(this, \"m_$agent_parent{$agent}_env\", \"config\", m_${agent}_config);\n", "", ""); } } else { # agent_has_env = yes. Add config to agent's own env align(" uvm_config_db #(${agent}_config)::set(this, \"m_${agent}_env\", \"config${suffix}\", m_${agent}${suffix}_config);\n", "", ""); } gen_aligned(); } } if ( keys %ref_model ) { print FH "\n"; print FH " // Default factory overrides for Syosil scoreboard\n"; print FH " cl_syoscb_queue::type_id::set_type_override(cl_syoscb_queue_std::type_id::get());\n"; } foreach my $ref_model_name ( keys %ref_model ) { print FH "\n"; print FH " begin\n"; print FH " bit ok;\n"; print FH " uvm_factory factory = uvm_factory::get();\n"; print FH "\n"; unless (exists $ref_model_compare_method{$ref_model_name}) { $ref_model_compare_method{$ref_model_name} = "iop"; } print FH " if (factory.find_override_by_type(cl_syoscb_compare_base::type_id::get(), \"*\") == cl_syoscb_compare_base::type_id::get())\n"; 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"; print FH "\n"; print FH " // Configuration object for Syosil scoreboard\n"; print FH " m_${ref_model_name}_config = cl_syoscb_cfg::type_id::create(\"m_${ref_model_name}_config\");\n"; print FH " m_${ref_model_name}_config.set_queues( {\"DUT\", \"REF\"} );\n"; print FH " ok = m_${ref_model_name}_config.set_primary_queue(\"DUT\");\n"; print FH " assert(ok);\n"; #foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) { # print FH " ok = m_${ref_model_name}_config.set_producer(\"$input\", {\"DUT\"} );\n"; # print FH " assert(ok);\n"; #} foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) { print FH " ok = m_${ref_model_name}_config.set_producer(\"$output\", {\"DUT\", \"REF\"} );\n"; print FH " assert(ok);\n"; } print FH "\n"; print FH " uvm_config_db#(cl_syoscb_cfg)::set(this, \"m_${ref_model_name}_scoreboard\", \"cfg\", m_${ref_model_name}_config);\n"; print FH "\n"; print FH " // Instantiate reference model and Syosil scoreboard\n"; align(" m_${ref_model_name} ", "= ${ref_model_name}", "::type_id::create(\"m_${ref_model_name}\", this);"); #foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) { # print FH " m_converter_${input} = converter_${input}_t::type_id::create(\"m_converter_${input}\", this);\n"; #} foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) { my $name = $output; $name =~ s/\./__/g; align(" m_converter_${name} ", "= converter_${name}_t", "::type_id::create(\"m_converter_${name}\", this);"); } align(" m_${ref_model_name}_scoreboard ", "= cl_syoscb", "::type_id::create(\"m_${ref_model_name}_scoreboard\", this);"); gen_aligned(); print FH " end\n"; } print FH "\n"; foreach my $agent (@agent_list) { align(" m_${agent}_env ", "= ${agent}_env", "::type_id::create(\"m_${agent}_env\", this);") if !grep( /$agent/, @stand_alone_agents ); } foreach my $aname (@top_env_agents) { for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$aname}); align("\n", "", ""); align(" m_${aname}${suffix}_agent ", "= ${aname}_agent ", "::type_id::create(\"m_${aname}${suffix}_agent\", this);"); align(" m_${aname}${suffix}_coverage ", "= ${aname}_coverage", "::type_id::create(\"m_${aname}${suffix}_coverage\", this);"); } } align("\n", "", ""); gen_aligned(); 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); print FH "endfunction : build_phase\n"; print FH "\n"; print FH "\n"; print FH "function void ${tbname}_env::connect_phase(uvm_phase phase);\n"; print FH " `uvm_info(get_type_name(), \"In connect_phase\", UVM_HIGH)\n"; foreach my $env (@env_list) { print FH " `uvm_info(get_type_name(), \$sformatf(\"m_${env}: %p\\n\",m_${env}), UVM_HIGH)\n"; } print FH "\n"; foreach my $aname (@top_env_agents) { for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$aname}); print FH " m_${aname}${suffix}_agent.analysis_port.connect(m_${aname}${suffix}_coverage.analysis_export);\n"; print FH "\n"; } } if ( $regmodel ) { print FH " // Connect the register model in each agent's env\n"; foreach my $agent ( keys(%reg_access_mode) ) { for ( my $i = 0 ; $i < $number_of_instances{$agent} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent}); print FH " m_${agent}_env.m_${agent}2reg_predictor${suffix}.map = regmodel.${reg_access_map{$agent}}${suffix};\n"; print FH " m_${agent}_env.m_${agent}2reg_predictor${suffix}.adapter = m_${agent}_env.m_reg2${agent}${suffix};\n"; print FH " regmodel.${reg_access_map{$agent}}${suffix}.set_sequencer(m_${agent}_env.m_${agent}${suffix}_agent.m_sequencer, ", "m_${agent}_env.m_reg2${agent}${suffix});\n"; print FH " regmodel.${reg_access_map{$agent}}${suffix}.set_auto_predict(0);\n"; print FH "\n"; } } } foreach my $ref_model_name ( keys(%ref_model) ) { print FH " begin\n"; print FH " // Connect reference model and Syosil scoreboard\n"; print FH " cl_syoscb_subscriber subscriber;\n"; print FH "\n"; my $i = 0; foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) { print FH " ${input}.analysis_port.connect(m_${ref_model_name}.analysis_export_$i);\n"; #print FH " subscriber = m_${ref_model_name}_scoreboard.get_subscriber(\"DUT\", \"${input}\");\n"; #print FH " ${input}.analysis_port.connect(m_converter_${input}.analysis_export);\n"; #print FH " m_converter_${input}.analysis_port.connect(subscriber.analysis_export);\n"; $i++; } $i = 0; foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) { print FH "\n"; print FH " subscriber = m_${ref_model_name}_scoreboard.get_subscriber(\"REF\", \"${output}\");\n"; print FH " m_${ref_model_name}.analysis_port_$i.connect(subscriber.analysis_export);\n"; print FH "\n"; print FH " subscriber = m_${ref_model_name}_scoreboard.get_subscriber(\"DUT\", \"${output}\");\n"; my $name = $output; $name =~ s/\./__/g; print FH " ${output}.analysis_port.connect(m_converter_${name}.analysis_export);\n"; print FH " m_converter_${name}.analysis_port.connect(subscriber.analysis_export);\n"; $i++; } print FH " end\n"; } print FH "\n"; 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); print FH "endfunction : connect_phase\n"; print FH "\n"; print FH "\n"; unless ( defined $top_env_generate_end_of_elaboration && $top_env_generate_end_of_elaboration eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH "function void ${tbname}_env::end_of_elaboration_phase(uvm_phase phase);\n"; print FH " uvm_factory factory = uvm_factory::get();\n"; print FH " `uvm_info(get_type_name(), \"Information printed from ${tbname}_env::end_of_elaboration_phase method\", UVM_MEDIUM)\n"; print FH " `uvm_info(get_type_name(), \$sformatf(\"Verbosity threshold is %d\", get_report_verbosity_level()), UVM_MEDIUM)\n"; print FH " uvm_top.print_topology();\n"; print FH " factory.print();\n"; print FH "endfunction : end_of_elaboration_phase\n"; print FH "\n"; print FH "\n"; } unless ( defined $top_env_generate_run_phase && $top_env_generate_run_phase eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH "// You can remove run_phase by setting top_env_generate_run_phase = no in file ${common_tpl_fname}\n\n"; } print FH "task ${tbname}_env::run_phase(uvm_phase phase);\n"; print FH " ${tbname}_default_seq vseq;\n"; print FH " vseq = ${tbname}_default_seq::type_id::create(\"vseq\");\n"; print FH " vseq.set_item_context(null, null);\n"; print FH " if ( !vseq.randomize() )\n"; print FH " `uvm_fatal\(get_type_name(), \"Failed to randomize virtual sequence\")\n"; foreach my $agent (@agent_list) { if ( not (grep( /$agent/, @stand_alone_agents ) or ( $agent eq "" ) ) ) { align(" vseq.m_${agent}_env ", "= m_${agent}_env;", ""); } } foreach my $aname (@top_env_agents) { for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$aname}); align(" vseq.m_${aname}${suffix}_agent ", "= m_${aname}${suffix}_agent;", ""); } } if ( $regmodel ) { align(" vseq.regmodel ", "= regmodel;", ""); } align(" vseq.m_config ", "= m_config;", ""); gen_aligned(); print FH " vseq.set_starting_phase(phase);\n"; print FH " vseq.start(null);\n"; print FH "\n"; 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); print FH "endtask : run_phase\n"; print FH "\n"; print FH "\n"; } } insert_inc_file("", $top_env_inc_after_class, $top_env_inc_after_inline, "top_env_inc_after_class", $common_tpl_fname); print FH "`endif // " . uc($tbname) . "_ENV_SV\n"; print FH "\n"; close(FH); } sub gen_port_converter { # Port converter class is only necessary if there is a reference model unless ( keys %ref_model ) { return; } $dir = $project . "/tb/" . $tbname; open( FH, ">" . $dir . "/sv/port_converter.sv" ) || die "Exiting due to Error: can't open env: $tbname"; write_file_header "port_converter.sv", "Analysis port type converter class for use with Syosil scoreboard"; unless ( defined $syosil_scoreboard_src_path ) { warning_prompt("ref_model specified in $common_tpl_fname but \$syosil_scoreboard_src_path has not been defined"); } print FH "`ifndef PORT_CONVERTER_SV\n"; print FH "`define PORT_CONVERTER_SV\n"; print FH "\n"; print FH "\n"; print FH "class port_converter #(type T = uvm_sequence_item) extends uvm_subscriber #(T);\n"; print FH " `uvm_component_param_utils(port_converter#(T))\n"; print FH "\n"; print FH " // For connecting analysis port of monitor to analysis export of Syosil scoreboard\n"; print FH "\n"; print FH " uvm_analysis_port #(uvm_sequence_item) analysis_port;\n"; print FH "\n"; print FH " function new(string name, uvm_component parent);\n"; print FH " super.new(name, parent);\n"; print FH " analysis_port = new(\"a_port\", this);\n"; print FH " endfunction\n"; print FH "\n"; print FH " function void write(T t);\n"; print FH " analysis_port.write(t);\n"; print FH " endfunction\n"; print FH "\n"; print FH "endclass\n"; print FH "\n"; print FH "\n"; print FH "`endif // PORT_CONVERTER_SV\n"; print FH "\n"; close(FH); } sub gen_ref_model { my ($ref_model_name) = @_; $dir = $project . "/tb/" . $tbname; open( FH, ">" . $dir . "/sv/$ref_model_name.sv" ) || die "Exiting due to Error: can't open env: $tbname"; write_file_header "$ref_model_name.sv", "Reference model for use with Syosil scoreboard"; unless ( defined $syosil_scoreboard_src_path ) { warning_prompt("ref_model specified in $common_tpl_fname but \$syosil_scoreboard_src_path has not been defined"); } print FH "`ifndef " . uc($ref_model_name) . "_SV\n"; print FH "`define " . uc($ref_model_name) . "_SV\n"; print FH "\n"; 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); print FH "\n"; my $i = 0; foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) { print FH "`uvm_analysis_imp_decl(_${ref_model_name}_$i)\n"; $i++; } print FH "\n"; print FH "class $ref_model_name extends uvm_component;\n"; print FH " `uvm_component_utils($ref_model_name)\n"; print FH "\n"; $i = 0; foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) { unless (exists ${agent_type_by_inst{$input}}) { 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"); } $agent_name = ${agent_type_by_inst{$input}}; print FH " uvm_analysis_imp_${ref_model_name}_$i #($agent_item_types{$agent_name}, $ref_model_name) analysis_export_$i; // $input\n"; $i++; } print FH "\n"; $i = 0; foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) { $agent_name = ${agent_type_by_inst{$output}}; if ($agent_name eq "") { 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"); } print FH " uvm_analysis_port #(uvm_sequence_item) analysis_port_$i; // $output\n"; $i++; } print FH "\n"; print FH " extern function new(string name, uvm_component parent);\n"; $i = 0; foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) { $agent_name = ${agent_type_by_inst{$input}}; print FH " extern function void write_${ref_model_name}_$i(input " . $agent_item_types{$agent_name} . " t);\n"; $i++; } print FH "\n"; 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); print FH "endclass\n"; print FH "\n"; print FH "\n"; print FH "function ${ref_model_name}::new(string name, uvm_component parent);\n"; print FH " super.new(name, parent);\n"; $i = 0; foreach my $input ( @{ $ref_model_inputs{$ref_model_name} } ) { print FH " analysis_export_$i = new(\"analysis_export_$i\", this);\n"; $i++; } $i = 0; foreach my $output ( @{ $ref_model_outputs{$ref_model_name} } ) { print FH " analysis_port_$i = new(\"analysis_port_$i\", this);\n"; $i++; } print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; 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); print FH "`endif // " . uc($ref_model_name) . "_SV\n"; print FH "\n"; } sub gen_top_config { $dir = $project . "/tb/" . $tbname; open( FH, ">" . $dir . "/sv/" . $tbname . "_config.sv" ) || die "Exiting due to Error: can't open config: $tbname"; write_file_header "${tbname}_config.sv", "Configuration for $tbname"; print FH "`ifndef " . uc($tbname) . "_CONFIG_SV\n"; print FH "`define " . uc($tbname) . "_CONFIG_SV\n"; print FH "\n"; insert_inc_file("", $top_env_config_inc_before_class, $top_env_config_inc_before_inline, "top_env_config_inc_before_class", $common_tpl_fname); print FH "class ${tbname}_config extends uvm_object;\n"; print FH "\n"; print FH " // Do not register config class with the factory\n"; print FH "\n"; if ( defined $nested_config_objects && $nested_config_objects eq "YES" ) { for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) { my $agent = $agent_list[$i]; for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) { my $suffix = calc_suffix($j, $number_of_instances{$agent}); align(" rand ${agent}_config ", "m_${agent}${suffix}_config;", ""); } } } else { for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) { my $agent = $agent_list[$i]; for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) { my $suffix = calc_suffix($j, $number_of_instances{$agent}); align(" virtual ${all_agent_ifs[$i]} ", "${agent}${suffix}_vif;", ""); } } align("\n", "", ""); for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) { my $agent = $agent_list[$i]; for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) { my $suffix = calc_suffix($j, $number_of_instances{$agent}); align(" uvm_active_passive_enum ", "is_active_${agent}${suffix} ", "= UVM_ACTIVE;"); } } align("\n", "", "") if ( @all_agent_ifs > 1); for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) { my $agent = $agent_list[$i]; for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) { my $suffix = calc_suffix($j, $number_of_instances{$agent}); align(" bit ", "checks_enable_${agent}${suffix};", ""); } } align("\n", "", "") if ( @all_agent_ifs > 1); for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) { my $agent = $agent_list[$i]; for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) { my $suffix = calc_suffix($j, $number_of_instances{$agent}); align(" bit ", "coverage_enable_${agent}${suffix};", ""); } } } gen_aligned(); print FH "\n"; unless ( @common_config_var_array ) { print FH " // You can insert variables here by setting config_var in file ${common_tpl_fname}\n"; } foreach my $var_decl (@common_config_var_array) { print FH " $var_decl\n"; } print FH "\n"; unless ( defined $top_env_config_generate_methods_inside_class && $top_env_config_generate_methods_inside_class eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH " // You can remove new by setting top_env_config_generate_methods_inside_class = no in file ${common_tpl_fname}\n\n"; } print FH " extern function new(string name = \"\");\n"; print FH "\n"; } insert_inc_file(" ", $top_env_config_inc_inside_class, $top_env_config_inc_inside_inline, "top_env_config_inc_inside_class", $common_tpl_fname); print FH "endclass : " . $tbname . "_config \n"; print FH "\n"; print FH "\n"; unless ( defined $top_env_config_generate_methods_after_class && $top_env_config_generate_methods_after_class eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH "// You can remove new by setting top_env_config_generate_methods_after_class = no in file ${common_tpl_fname}\n\n"; } print FH "function ${tbname}_config::new(string name = \"\");\n"; print FH " super.new(name);\n"; print FH "\n"; if ( defined $nested_config_objects && $nested_config_objects eq "YES" ) { for ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) { my $agent = $agent_list[$i]; for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) { my $suffix = calc_suffix($j, $number_of_instances{$agent}); align(" m_${agent}${suffix}_config ", "= new(\"m_${agent}${suffix}_config\");", ""); my $value; if ( exists $agent_is_active{$agent} ) { $value = "$agent_is_active{$agent}"; } else { $value = "UVM_ACTIVE"; } align(" m_${agent}${suffix}_config.is_active ", "= $value;", ""); if ( exists $agent_checks_enable{$agent} and $agent_checks_enable{$agent} eq "NO" ) { $value = "0"; } else { $value = "1"; } align(" m_${agent}${suffix}_config.checks_enable ", "= $value;", ""); if ( exists $agent_coverage_enable{$agent} and $agent_coverage_enable{$agent} eq "NO" ) { $value = "0"; } else { $value = "1"; } align(" m_${agent}${suffix}_config.coverage_enable ", "= $value;", ""); align("\n", "", ""); } } gen_aligned(); } 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); print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; } insert_inc_file("", $top_env_config_inc_after_class, $top_env_config_inc_after_inline, "top_env_config_inc_after_class", $common_tpl_fname); print FH "`endif // " . uc($tbname) . "_CONFIG_SV\n"; print FH "\n"; close(FH); } sub gen_top_seq_lib { $dir = $project . "/tb/" . $tbname; open( FH, ">" . $dir . "/sv/" . $tbname . "_seq_lib.sv" ) || die "Exiting due to Error: can't open seq_lib: $tbname"; write_file_header "${tbname}_seq_lib.sv", "Sequence for $tbname"; print FH "`ifndef " . uc($tbname) . "_SEQ_LIB_SV\n"; print FH "`define " . uc($tbname) . "_SEQ_LIB_SV\n"; print FH "\n"; print FH "class ${tbname}_default_seq extends uvm_sequence #(uvm_sequence_item);\n"; print FH "\n"; print FH " `uvm_object_utils(" . $tbname . "_default_seq)\n"; print FH "\n"; if ( $regmodel ) { align(" $top_reg_block_type ", "regmodel;", ""); } align(" ${tbname}_config ", "m_config;\n", ""); foreach my $agent (@agent_list) { do { align(" ${agent}_env ", "m_${agent}_env;", ""); } unless grep( /$agent/, @stand_alone_agents ); } foreach my $aname (@top_env_agents) { for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$aname}); align(" ${aname}_agent ", "m_${aname}${suffix}_agent;", ""); } } foreach my $env (@env_list) { $env =~ /(\w+)_env/; if ( exists $reg_access_mode{$1} ) { push @reg_env, $1; align(" ${env}_default_seq ", "m_${env}_seq;", ""); } else { #env that does not access regmodel push @non_reg_env, $1; align(" ${1}_env_default_seq ", "m_${1}_env_seq;", ""); } } gen_aligned(); print FH "\n"; print FH " // Number of times to repeat child sequences\n"; if ( defined $top_default_seq_count ) { print FH " int m_seq_count = $top_default_seq_count;\n"; } else { print FH " int m_seq_count = 1;\n"; } print FH "\n"; do { print FH "\n"; print FH " // Example built-in register sequences\n"; print FH " //uvm_reg_hw_reset_seq m_reset_seq;\n"; print FH " //uvm_reg_bit_bash_seq m_bit_bash_seq;\n"; print FH "\n"; } if $regmodel; print FH " extern function new(string name = \"\");\n"; print FH " extern task body();\n"; print FH " extern task pre_start();\n"; print FH " extern task post_start();\n"; print FH "\n"; print FH "`ifndef UVM_POST_VERSION_1_1\n"; print FH " // Functions to support UVM 1.2 objection API in UVM 1.1\n"; print FH " extern function uvm_phase get_starting_phase();\n"; print FH " extern function void set_starting_phase(uvm_phase phase);\n"; print FH "`endif\n"; print FH "\n"; print FH "endclass : " . $tbname . "_default_seq\n"; print FH "\n"; print FH "\n"; print FH "function ${tbname}_default_seq::new(string name = \"\");\n"; print FH " super.new(name);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; print FH "task ${tbname}_default_seq::body();\n"; print FH " `uvm_info(get_type_name(), \"Default sequence starting\", UVM_HIGH)\n"; print FH "\n"; foreach my $env (@reg_env, @non_reg_env) { align(" m_${env}_env_seq ", "= ${env}_env_default_seq", "::type_id::create(\"m_${env}_env_seq\");"); # For the purposes of random stability, although the virtual sequence is actually running on the null sequencer, # pretend instead that it is running on the sequencer of the agent. # If there are multiple instances of the agent, pick the first my $suffix = calc_suffix(0, $number_of_instances{$env}); my $sequencer_instance_name = "m_${env}_env.m_${env}${suffix}_agent.m_sequencer"; align(" m_${env}_env_seq.set_item_context(this, ${sequencer_instance_name});\n", "", ""); align(" m_${env}_env_seq.set_starting_phase( get_starting_phase() );\n", "", ""); if ( grep( /$env/, @reg_env ) ) { $aname = $env; for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$aname}); if ( ${reg_access_instance{$aname}} ne "" ) { align(" m_${env}_env_seq.regmodel${suffix} ", "= regmodel${reg_access_instance{$aname}}${suffix};", ""); } else { # If instance = "", use the top-level regmodel align(" m_${env}_env_seq.regmodel${suffix} ", "= regmodel;", ""); } align(" m_${env}_env_seq.m_config${suffix} ", "= m_${aname}_env.m_${aname}${suffix}_agent.m_config;", ""); } } align("\n", "", ""); } gen_aligned(); print FH "\n"; print FH " repeat (m_seq_count)\n"; print FH " begin\n"; my @vseq_list; if ($regmodel) { foreach my $env (@reg_env) { print FH " if ( !m_${env}_env_seq.randomize() )\n"; print FH " `uvm_error(get_type_name(), \"Failed to randomize sequence\")\n"; push @vseq_list, "m_${env}_env_seq"; } } foreach my $env (@non_reg_env) { push @vseq_list, "m_${env}_env_seq"; print FH " if ( !m_${env}_env_seq.randomize() )\n"; print FH " `uvm_error(get_type_name(), \"Failed to randomize sequence\")\n"; print FH " m_${env}_env_seq.m_env = m_${env}_env;\n"; } print FH " fork\n"; foreach my $vseq (@vseq_list) { print FH " ${vseq}.start(null, this);\n"; } foreach my $aname (@top_env_agents) { for ( my $i = 0 ; $i < $number_of_instances{$aname} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$aname}); my $sequencer_instance_name = "m_${aname}${suffix}_agent.m_sequencer"; print FH " if (m_${aname}${suffix}_agent.m_config.is_active == UVM_ACTIVE)\n"; print FH " begin\n"; print FH " ${aname}_default_seq seq;\n"; print FH " seq = ${aname}_default_seq::type_id::create(\"seq\");\n"; print FH " seq.set_item_context(this, ${sequencer_instance_name});\n"; print FH " if ( !seq.randomize() )\n"; print FH " `uvm_error(get_type_name(), \"Failed to randomize sequence\")\n"; print FH " seq.m_config = m_${aname}${suffix}_agent.m_config;\n"; print FH " seq.set_starting_phase( get_starting_phase() );\n"; print FH " seq.start(${sequencer_instance_name}, this);\n"; print FH " end\n"; } } print FH " join\n"; print FH " end\n"; print FH "\n"; print FH " `uvm_info(get_type_name(), \"Default sequence completed\", UVM_HIGH)\n"; print FH "endtask : body\n"; print FH "\n"; print FH "\n"; print FH "task ${tbname}_default_seq::pre_start();\n"; print FH " uvm_phase phase = get_starting_phase();\n"; print FH " if (phase != null)\n"; print FH " phase.raise_objection(this);\n"; print FH "endtask: pre_start\n"; print FH "\n"; print FH "\n"; print FH "task ${tbname}_default_seq::post_start();\n"; print FH " uvm_phase phase = get_starting_phase();\n"; print FH " if (phase != null) \n"; print FH " phase.drop_objection(this);\n"; print FH "endtask: post_start\n"; print FH "\n"; print FH "\n"; print FH "`ifndef UVM_POST_VERSION_1_1\n"; print FH "function uvm_phase ${tbname}_default_seq::get_starting_phase();\n"; print FH " return starting_phase;\n"; print FH "endfunction: get_starting_phase\n"; print FH "\n"; print FH "\n"; print FH "function void ${tbname}_default_seq::set_starting_phase(uvm_phase phase);\n"; print FH " starting_phase = phase;\n"; print FH "endfunction: set_starting_phase\n"; print FH "`endif\n"; print FH "\n"; print FH "\n"; insert_inc_file("", $top_seq_inc, $top_seq_inc_inline, "top_seq_inc", $common_tpl_fname); print FH "`endif // " . uc($tbname) . "_SEQ_LIB_SV\n"; print FH "\n"; close(FH); } sub gen_top_test { $dir = $project . "/tb/" . $tbname . "_test"; open( FH, ">" . $dir . "/sv/" . $tbname . "_test_pkg.sv" ) || die "can't open test: " . $tbname . "_test_pkg.sv"; write_file_header "${tbname}_test_pkg.sv", "Test package for $tbname"; print FH "`ifndef " . uc($tbname) . "_TEST_PKG_SV\n"; print FH "`define " . uc($tbname) . "_TEST_PKG_SV\n"; print FH "\n"; print FH "package " . $tbname . "_test_pkg;\n"; print FH "\n"; print FH " `include \"uvm_macros.svh\"\n"; print FH "\n"; print FH " import uvm_pkg::*;\n"; print FH "\n"; print FH " import regmodel_pkg::*;\n\n" if $regmodel; print FH " import ${common_pkg}::*;\n" if $common_pkg; print FH " import ${common_env_pkg}::*;\n" if $common_env_pkg; foreach my $agent (@agent_list) { print FH " import ${agent}_pkg::*;\n"; } print FH " import " . $tbname . "_pkg::*;\n"; print FH "\n"; print FH " `include \"" . $tbname . "_test.sv\"\n"; print FH "\n"; print FH "endpackage : " . $tbname . "_test_pkg\n"; print FH "\n"; print FH "`endif // " . uc($tbname) . "_TEST_PKG_SV\n"; print FH "\n"; close(FH); $dir = $project . "/tb/" . $tbname . "_test"; # define specific tests $dir = $project . "/tb/" . $tbname . "_test"; open( FH, ">" . $dir . "/sv/" . $tbname . "_test.sv" ) || die "Exiting due to Error: can't open test: " . $tbname . "_test.sv"; write_file_header "${tbname}_test.sv", "Test class for ${tbname} (included in package ${tbname}_test_pkg)"; print FH "`ifndef " . uc($tbname) . "_TEST_SV\n"; print FH "`define " . uc($tbname) . "_TEST_SV\n"; print FH "\n"; insert_inc_file("", $test_inc_before_class, $test_inc_before_inline, "test_inc_before_class", $common_tpl_fname); print FH "class ${tbname}_test extends uvm_test;\n"; print FH "\n"; print FH " `uvm_component_utils(" . $tbname . "_test)\n"; print FH "\n"; print FH " ${tbname}_env m_env;\n"; print FH "\n"; print FH " extern function new(string name, uvm_component parent);\n"; print FH "\n"; unless ( defined $test_generate_methods_inside_class && $test_generate_methods_inside_class eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH " // You can remove build_phase method by setting test_generate_methods_inside_class = no in file ${common_tpl_fname}\n\n"; } print FH " extern function void build_phase(uvm_phase phase);\n"; print FH "\n"; } insert_inc_file(" ", $test_inc_inside_class, $test_inc_inside_inline, "test_inc_inside_class", $common_tpl_fname); print FH "endclass : ${tbname}_test\n"; print FH "\n"; print FH "\n"; print FH "function ${tbname}_test::new(string name, uvm_component parent);\n"; print FH " super.new(name, parent);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; unless ( defined $test_generate_methods_after_class && $test_generate_methods_after_class eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH "// You can remove build_phase method by setting test_generate_methods_after_class = no in file ${common_tpl_fname}\n\n"; } print FH "function void ${tbname}_test::build_phase(uvm_phase phase);\n"; print FH "\n"; insert_inc_file(" ", $test_prepend_to_build_phase, $test_prepend_to_build_phase_inline, "test_prepend_to_build_phase", $common_tpl_fname); print FH " // You could modify any test-specific configuration object variables here\n"; print FH "\n"; do { print FH " // Include reg coverage from the register model\n"; print FH " uvm_reg::include_coverage(\"*\", UVM_CVR_ALL);\n"; } if $regmodel; print FH "\n"; foreach my $factory_override ( keys %agent_factory_set ) { if ($factory_override ne "") { align(" ${factory_override}", "::type_id::set_type_override($agent_factory_set{$factory_override}::get_type());", ""); } } foreach my $factory_override ( keys %top_factory_set ) { if ($factory_override ne "") { align(" ${factory_override}", "::type_id::set_type_override($top_factory_set{$factory_override}::get_type());", ""); } } gen_aligned(); print FH "\n"; print FH " m_env = ${tbname}_env::type_id::create(\"m_env\", this);\n"; print FH "\n"; insert_inc_file(" ", $test_append_to_build_phase, $test_append_to_build_phase_inline, "test_append_to_build_phase", $common_tpl_fname); print FH "endfunction : build_phase\n"; print FH "\n"; print FH "\n"; } insert_inc_file("", $test_inc_after_class, $test_inc_after_inline, "test_inc_after_class", $common_tpl_fname); print FH "`endif // " . uc($tbname) . "_TEST_SV\n"; print FH "\n"; close(FH); } sub gen_top() { ### generate top modules $dir = $project . "/tb/" . $tbname; ### Test Harness open( FH, ">" . $dir . "_tb/sv/" . $tbname . "_th.sv" ) || die "Exiting due to Error: can't open include file: " . $tbname . "_th.sv"; write_file_header "${tbname}_th.sv", "Test Harness"; if ( $split_transactors eq "YES" ) { $th_module_name = "${tbname}_hdl_th"; } else { $th_module_name = "${tbname}_th"; } print FH "module ${th_module_name};\n"; print FH "\n"; print FH " timeunit $timeunit;\n"; print FH " timeprecision $timeprecision;\n"; print FH "\n"; print FH " import ${common_pkg}::*;\n" if $common_pkg; print FH " import ${common_env_pkg}::*;\n" if $common_env_pkg; print FH "\n"; unless ( defined $th_generate_clock_and_reset && $th_generate_clock_and_reset eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH " // You can remove clock and reset below by setting th_generate_clock_and_reset = no in file ${common_tpl_fname}\n\n"; } print FH " // Example clock and reset declarations\n"; print FH " logic clock = 0;\n"; print FH " logic reset;\n"; print FH "\n"; print FH " // Example clock generator process\n"; print FH " always #10 clock = ~clock;\n"; print FH "\n"; print FH " // Example reset generator process\n"; print FH " initial\n"; print FH " begin\n"; print FH " reset = 0; // Active low reset in this example\n"; print FH " #75 reset = 1;\n"; print FH " end\n"; if (@rlist) {# align("\n", "", ""); for ( $i = 0 ; $i < @rlist ; $i = $i + 2 ) { $agent_name = $rlist[$i]; unless ( exists $generate_interface_instance{$agent_name} && $generate_interface_instance{$agent_name} eq "NO" ) { for ( my $j = 0 ; $j < $number_of_instances{$agent_name} ; $j++ ) { my $suffix = "_${j}"; align(" assign ${agent_name}_if${suffix}.$rlist[ $i + 1 ] ", "= reset;", ""); } } } } if (@clist) { align("\n", "", ""); for ( $i = 0 ; $i < @clist ; $i = $i + 2 ) { $agent_name = $clist[$i]; unless ( exists $generate_interface_instance{$agent_name} && $generate_interface_instance{$agent_name} eq "NO" ) { for ( my $j = 0 ; $j < $number_of_instances{$agent_name} ; $j++ ) { my $suffix = "_${j}"; align(" assign ${agent_name}_if${suffix}.$clist[ $i + 1 ] ", "= clock;", ""); } } } } gen_aligned(); print FH "\n"; } insert_inc_file(" ", $th_inc_inside_module, $th_inc_inside_inline, "th_inc_inside_module", $common_tpl_fname); align(" // Pin-level interfaces connected to DUT\n", "", ""); unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { align(" // You can remove interface instances by setting generate_interface_instance = no in the interface template file\n\n", "", ""); } foreach my $agent_name (@agent_list) { unless ( exists $generate_interface_instance{$agent_name} && $generate_interface_instance{$agent_name} eq "NO" ) { my $interface_type; if ( exists $byo_interface{$agent_name} ) { $interface_type = $byo_interface{$agent_name}; } else { $interface_type = "${agent_name}_if"; } for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) { my $suffix = "_${i}"; align(" ${interface_type} ", "${agent_name}_if${suffix} ();", ""); } } } align("\n", "", ""); if ( $split_transactors eq "YES" ) { align(" // BFM interfaces that communicate with proxy transactors in UVM environment\n", "", ""); foreach my $agent_name (@agent_list) { for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) { my $suffix = "_${i}"; align(" ${agent_name}_bfm ", "${agent_name}_bfm${suffix} (${agent_name}_if${suffix});", ""); } } align("\n", "", ""); } gen_aligned(); gen_dut_inst(); print FH "\n"; print FH "endmodule\n"; print FH "\n"; close(FH); ###Testbench open( FH, ">" . $dir . "_tb/sv/" . $tbname . "_tb.sv" ) || die "Exiting due to Error: can't open include file: ${tbname}_tb.sv"; write_file_header("${tbname}_tb.sv","Testbench"); if ( $split_transactors eq "YES" ) { $tb_module_name = "${tbname}_untimed_tb"; } else { $tb_module_name = "${tbname}_tb"; } print FH "module ${tb_module_name};\n"; print FH "\n"; print FH " timeunit $timeunit;\n"; print FH " timeprecision $timeprecision;\n"; print FH "\n"; print FH " `include \"uvm_macros.svh\"\n"; print FH "\n"; print FH " import uvm_pkg::*;\n"; print FH "\n"; print FH " import ${common_pkg}::*;\n" if $common_pkg; print FH " import ${common_env_pkg}::*;\n" if $common_env_pkg; print FH " import ${tbname}_test_pkg::*;\n"; print FH " import ${tbname}_pkg::${tbname}_config;\n"; print FH "\n"; print FH " // Configuration object for top-level environment\n"; print FH " ${tbname}_config top_env_config;\n"; print FH "\n"; unless ( $dual_top eq "YES" ) { print FH " // Test harness\n"; print FH " ${th_module_name} th();\n"; print FH "\n"; } insert_inc_file(" ", $tb_inc_inside_module, $tb_inc_inside_inline, "tb_inc_inside_module", $common_tpl_fname); unless ( defined $tb_generate_run_test && $tb_generate_run_test eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH " // You can remove the initial block below by setting tb_generate_run_test = no in file ${common_tpl_fname}\n\n"; } print FH " initial\n"; print FH " begin\n"; insert_inc_file(" ", $tb_prepend_to_initial, $tb_prepend_to_initial_inline, "tb_prepend_to_initial", $common_tpl_fname); print FH " // Create and populate top-level configuration object\n"; print FH " top_env_config = new(\"top_env_config\");\n"; print FH " if ( !top_env_config.randomize() )\n"; print FH " `uvm_error(\"${tb_module_name}\", \"Failed to randomize top-level configuration object\" )\n"; print FH "\n"; foreach ( my $i = 0 ; $i < @all_agent_ifs ; $i++ ) { my $agent = $agent_list[$i]; for ( my $j = 0 ; $j < $number_of_instances{$agent} ; $j++ ) { my $suffix = calc_suffix($j, $number_of_instances{$agent}); my $test_harness_name; if ( $dual_top eq "YES" ) { $test_harness_name = ${th_module_name}; } else { $test_harness_name = "th"; } if ( defined $nested_config_objects && $nested_config_objects eq "YES" ) { unless ( exists $generate_interface_instance{$agent} && $generate_interface_instance{$agent} eq "NO" ) { align(" top_env_config.m_${agent}${suffix}_config.vif ", "= $test_harness_name.$all_agent_ifs[$i]_${j};", ""); } } else { unless ( exists $generate_interface_instance{$agent} && $generate_interface_instance{$agent} eq "NO" ) { align(" top_env_config.${agent}${suffix}_vif ", "= $test_harness_name.$all_agent_ifs[$i]_${j};", ""); } my $value; if ( exists $agent_is_active{$agent} ) { $value = "$agent_is_active{$agent}"; } else { $value = "UVM_ACTIVE"; } align(" top_env_config.is_active_${agent}${suffix} ", "= ${value};", ""); if ( exists $agent_checks_enable{$agent} and $agent_checks_enable{$agent} eq "NO" ) { $value = "0"; } else { $value = "1"; } align(" top_env_config.checks_enable_${agent}${suffix} ", "= ${value};", ""); if ( exists $agent_coverage_enable{$agent} and $agent_coverage_enable{$agent} eq "NO" ) { $value = "0"; } else { $value = "1"; } align(" top_env_config.coverage_enable_${agent}${suffix} ", "= ${value};", ""); align("\n", "", ""); } } } gen_aligned(); print FH "\n"; print FH " uvm_config_db #(${tbname}_config)::set(null, \"uvm_test_top\", \"config\", top_env_config);\n"; print FH " uvm_config_db #(${tbname}_config)::set(null, \"uvm_test_top.m_env\", \"config\", top_env_config);\n"; print FH "\n"; insert_inc_file(" ", $tb_inc_before_run_test, $tb_inc_before_run_test_inline, "tb_inc_before_run_test", $common_tpl_fname); print FH " run_test();\n"; print FH " end\n"; print FH "\n"; } print FH "endmodule\n"; print FH "\n"; close(FH); } sub gen_regmodel_pkg { my $line; print LOGFILE "\nProcessing register layer\n"; my $dir = $project . "/tb/regmodel"; printf LOGFILE "rdir: $dir\n"; mkdir( $dir, 0755 ); my $file1 = "./${regmodel_file}"; my $file2 = $project . "/tb/regmodel/${regmodel_file}"; print LOGFILE "file1: $file1\n"; print LOGFILE "file2: $file2\n"; #open regmodel file and put into package open( REGFILE_IN, "<" . $file1 ) || die "Exiting due to Error: can't open $file1"; open( REGFILE_OUT, ">" . $file2 ) || die "Exiting due to Error: can't open $file2"; my $guard_macro = ""; COPY_HEADER: { $line = <REGFILE_IN>; #write header without modification if ( $line =~ /^\s*$|^\s*\/\/.*$|^\s*\/\*.*$|^\s*`ifndef\s+([\w_]+).*/ ) { #blank line|comment|compiler directive if ($1) { $guard_macro = $1; } print REGFILE_OUT $line; redo COPY_HEADER; } } print REGFILE_OUT "package regmodel_pkg;\n"; print REGFILE_OUT "\n"; print REGFILE_OUT "import uvm_pkg::*;\n"; print REGFILE_OUT "`include \"uvm_macros.svh\"\n"; print REGFILE_OUT "\n"; print REGFILE_OUT "$line"; while ( $line = <REGFILE_IN> ) { #copy rest of package file last if ( $line =~ /\s*`endif\s+$guard_macro/ ); print REGFILE_OUT $line; } print REGFILE_OUT "\n"; print REGFILE_OUT "endpackage: regmodel_pkg\n"; print REGFILE_OUT "\n"; print REGFILE_OUT $line if $line; close(REGFILE_IN); close(REGFILE_OUT); } sub gen_regmodel_adapter { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/reg2" . $agent_name . "_adapter.sv" ) || die "Exiting due to Error: can't open adapter: reg2${agent_name}_adapter.sv"; write_file_header "${agent_name}_adapter.sv", "Environment for reg2 ${agent_name}_adapter.sv\n"; print FH "`ifndef REG2" . uc($agent_name) . "_ADAPTER_SV\n"; print FH "`define REG2" . uc($agent_name) . "_ADAPTER_SV\n"; print FH "\n"; 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}); print FH "class reg2${agent_name}_adapter extends uvm_reg_adapter;\n"; print FH "\n"; print FH " `uvm_object_utils(reg2" . $agent_name . "_adapter)\n"; print FH "\n"; print FH " extern function new(string name = \"\");\n"; print FH "\n"; unless ( exists $agent_adapter_generate_methods_inside_class{$agent_name} && $agent_adapter_generate_methods_inside_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH " // You can remove reg2bus and bus2reg by setting adapter_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n"; } print FH " extern function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);\n"; print FH " extern function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);\n"; print FH "\n"; } 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}); print FH "endclass : reg2" . $agent_name . "_adapter \n"; print FH "\n"; print FH "\n"; print FH "function reg2${agent_name}_adapter::new(string name = \"\");\n"; print FH " super.new(name);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; unless ( exists $agent_adapter_generate_methods_after_class{$agent_name} && $agent_adapter_generate_methods_after_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH "// You can remove reg2bus and bus2reg by setting adapter_generate_methods_after_class = no in file $tpl_fname{$agent_name}\n\n"; } print FH "function uvm_sequence_item reg2${agent_name}_adapter::reg2bus(const ref uvm_reg_bus_op rw);\n"; print FH " $agent_item_types{$agent_name} ${agent_name} = $agent_item_types{$agent_name}::type_id::create(\"${agent_name}\");\n"; if ( $reg_access_mode{$agent_name} =~ /WR|WO/i ) { align(" $agent_name.$bus2reg_map{$agent_name}->{'kind'} ", "= (rw.kind == UVM_READ) ? 0 : 1;", ""); align(" $agent_name.$bus2reg_map{$agent_name}->{'addr'} ", "= rw.addr;", ""); align(" $agent_name.$bus2reg_map{$agent_name}->{'data'} ", "= rw.data;", ""); gen_aligned(); 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"; } elsif ( $reg_access_mode{$agent_name} =~ /RO/i ) { align(" $agent_name.$bus2reg_map{$agent_name}->{'kind'} ", "= (rw.kind == UVM_READ) ? 0 : 1;", ""); align(" $agent_name.$bus2reg_map{$agent_name}->{'addr'} ", "= rw.addr;", ""); align(" $agent_name.$bus2reg_map{$agent_name}->{'data'} ", "= rw.data;", ""); gen_aligned(); 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"; print FH " if (rw.kind != UVM_READ) `uvm_warning(get_type_name(), \"Interface is READ-ONLY\")\n"; } else { warning_prompt("reg_access_mode is neither WR, WO, nor RO, so reg2${agent_name}_adapter is incomplete"); print FH " `uvm_warning(get_type_name(), \"Interface mode not specified\")\n"; } print FH " return " . $agent_name . ";\n"; print FH "endfunction : reg2bus\n"; print FH "\n"; print FH "\n"; print FH "function void reg2${agent_name}_adapter::bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);\n"; print FH " $agent_item_types{$agent_name} ${agent_name};\n"; print FH " if (!\$cast(${agent_name}, bus_item))\n"; print FH " `uvm_fatal(get_type_name(),\"Provided bus_item is not of the correct type\")\n"; if ( $reg_access_mode{$agent_name} =~ /WR|WO/i ) { print FH " rw.kind = $agent_name.$bus2reg_map{$agent_name}->{'kind'}" . " ? UVM_WRITE : UVM_READ;\n"; } else { print FH " rw.kind = UVM_READ;\n"; } print FH " rw.addr = $agent_name.$bus2reg_map{$agent_name}->{'addr'};\n"; print FH " rw.data = $agent_name.$bus2reg_map{$agent_name}->{'data'};\n"; print FH " rw.status = UVM_IS_OK;\n"; 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"; print FH "endfunction : bus2reg\n"; print FH "\n"; print FH "\n"; } 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}); print FH "\n"; print FH "`endif // REG2" . uc($agent_name) . "_ADAPTER_SV\n"; print FH "\n"; close(FH); } sub gen_regmodel_coverage { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_env_coverage.sv" ) || die "Exiting due to Error: can't open config: ${agent_name}_env_coverage.sv"; write_file_header "${agent_name}_env_coverage.sv", "Coverage for $agent_name env\n"; print FH "`ifndef " . uc($agent_name) . "_ENV_COVERAGE_SV\n"; print FH "`define " . uc($agent_name) . "_ENV_COVERAGE_SV\n"; print FH "\n"; 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}); print FH "class ${agent_name}_env_coverage extends uvm_subscriber #($agent_item_types{$agent_name});\n"; print FH "\n"; print FH " `uvm_component_utils(" . $agent_name . "_env_coverage)\n"; print FH "\n"; align(" ${agent_name}_config ", "m_config;", ""); align(" bit ", "m_is_covered;", ""); align(" $agent_item_types{$agent_name} ", "m_item;", ""); align(" $reg_access_block_type{$agent_name} ", "regmodel;\n", ""); gen_aligned(); #if include file for coverage collector exists, pull it in here, otherwise #create covergroup and coverpoints with default bins if ( exists $reg_cover_inc{$agent_name} && -e "${project}/tb/include/$reg_cover_inc{$agent_name}" ) { open(FH_COV, "<${project}/tb/include/$reg_cover_inc{$agent_name}") or die "CANNOT OPEN INCLUDE FILE reg_cover_inc{$agent_name}"; my $cov_inc = join("",<FH_COV>); #check that file contains covergroup named "m_cov" if ($cov_inc =~ /covergroup\s+m_cov(\s|;)/) { print FH " // Inserting covergroup from include file\n"; insert_inc_file(" ", $reg_cover_inc{$agent_name}, $reg_cover_inc_inline{$agent_name}, "", ""); } else { 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"; print FH " covergroup m_cov;\n"; print FH " option.per_instance = 1;\n"; print FH " // Inserting coverpoints from include file\n"; insert_inc_file(" ", $reg_cover_inc{$agent_name}, $reg_cover_inc_inline{$agent_name}, "", ""); print FH " endgroup: m_cov\n"; print FH "\n"; } } else { unless ( exists $reg_cover_generate_methods_inside_class{$agent_name} && $reg_cover_generate_methods_inside_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { print FH " // You can replace covergroup m_cov by setting reg_cover_inc in file $tpl_fname{$agent_name}\n"; print FH " // or remove covergroup m_cov by setting reg_cover_generate_methods_inside_class = no in file $tpl_fname{$agent_name}\n\n"; } print FH " covergroup m_cov;\n"; print FH " option.per_instance = 1;\n"; print FH " // You may insert additional coverpoints here ...\n"; print FH "\n"; print FH " endgroup\n"; print FH "\n"; } } unless ( exists $reg_cover_generate_methods_inside_class{$agent_name} && $reg_cover_generate_methods_inside_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH " extern function new(string name, uvm_component parent);\n"; print FH " extern function void write($agent_item_types{$agent_name} t);\n"; print FH " extern function void build_phase(uvm_phase phase);\n"; print FH " extern function void report_phase(uvm_phase phase);\n"; print FH "\n"; } 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}); print FH "endclass : " . $agent_name . "_env_coverage \n"; print FH "\n"; print FH "\n"; unless ( exists $reg_cover_generate_methods_after_class{$agent_name} && $reg_cover_generate_methods_after_class{$agent_name} eq "NO" ) { unless ( defined $comments_at_include_locations && $comments_at_include_locations eq "NO" ) { 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"; } print FH "function ${agent_name}_env_coverage::new(string name, uvm_component parent);\n"; print FH " super.new(name, parent);\n"; print FH " m_cov = new();\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_name}_env_coverage::write($agent_item_types{$agent_name} t);\n"; print FH " // Assign seq item properties to member variables\n"; print FH " m_item = t;\n"; print FH " m_cov.sample();\n"; print FH " // Check coverage - could use m_cov.option.goal instead of 100 if your simulator supports it\n"; print FH " if (m_cov.get_inst_coverage() >= 100) m_is_covered = 1;\n"; print FH "endfunction : write\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_name}_env_coverage::build_phase(uvm_phase phase);\n"; print FH " if (!uvm_config_db #(${agent_name}_config)::get(this, \"\", \"config\", m_config))\n"; print FH " `uvm_error(get_type_name(), \"${agent_name} config not found\")\n"; print FH "endfunction : build_phase\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_name}_env_coverage::report_phase(uvm_phase phase);\n"; print FH " if (m_config.coverage_enable)\n"; print FH " `uvm_info(get_type_name(), \$sformatf(\"Coverage score = %3.1f%%\", m_cov.get_inst_coverage()), UVM_MEDIUM)\n"; print FH " else\n"; print FH " `uvm_info(get_type_name(), \"Coverage disabled for this agent\", UVM_MEDIUM)\n"; print FH "endfunction : report_phase\n"; print FH "\n"; print FH "\n"; } 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}); print FH "`endif // " . uc($agent_name) . "_ENV_COVERAGE_SV\n"; print FH "\n"; close(FH); } sub gen_regmodel_seq_lib { $dir = $project . "/tb/" . $agent_name; open( FH, ">" . $dir . "/sv/" . $agent_name . "_env_seq_lib.sv" ) || die "Exiting due to Error: can't open seq_lib: " . $agent_name . "_env_seq_lib.sv"; write_file_header "${agent_name}_env_seq_lib.sv", "Sequence for $agent_name env\n"; print FH "`ifndef " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n"; print FH "`define " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n"; print FH "\n"; print FH "class ${agent_name}_env_default_seq extends uvm_sequence #($agent_item_types{$agent_name});\n"; print FH "\n"; print FH " `uvm_object_utils(" . $agent_name . "_env_default_seq)\n"; print FH "\n"; for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent_name}); align(" $reg_access_block_type{$agent_name} ", "regmodel${suffix};", ""); align(" ${agent_name}_config ", "m_config${suffix};", ""); } align("\n", "", ""); align(" uvm_status_e ", "status;", "// Returning access status"); align(" rand uvm_reg_data_t ", "data;", "// For passing data"); gen_aligned(); print FH "\n"; print FH " extern function new(string name = \"\");\n"; print FH " extern task body();\n"; print FH "\n"; print FH "`ifndef UVM_POST_VERSION_1_1\n"; print FH " // Functions to support UVM 1.2 objection API in UVM 1.1\n"; print FH " extern function uvm_phase get_starting_phase();\n"; print FH " extern function void set_starting_phase(uvm_phase phase);\n"; print FH "`endif\n"; print FH "\n"; print FH "endclass : " . $agent_name . "_env_default_seq\n"; print FH "\n"; print FH "\n"; print FH "function ${agent_name}_env_default_seq::new(string name = \"\");\n"; print FH " super.new(name);\n"; print FH "endfunction : new\n"; print FH "\n"; print FH "\n"; print FH "task ${agent_name}_env_default_seq::body();\n"; print FH " `uvm_info(get_type_name(), \"Default sequence starting\", UVM_HIGH)\n"; print FH "\n"; my $n = $number_of_instances{$agent_name}; print FH " fork\n" if $n > 1; for ( my $i = 0 ; $i < $n ; $i++ ) { my $suffix = calc_suffix($i, $n); print FH " begin\n"; print FH " uvm_reg data_regs[\$];\n"; print FH " regmodel${suffix}.get_registers(data_regs);\n"; print FH " data_regs.shuffle();\n"; print FH " foreach(data_regs[i])\n"; print FH " begin\n"; print FH " // Randomize register content and then update\n"; print FH " if ( !data_regs[i].randomize() )\n"; print FH " `uvm_error(get_type_name(), \$sformatf(\"Failed to randomize data_regs[%0d]\", i))\n"; print FH " data_regs[i].update(status, .path(UVM_FRONTDOOR), .parent(this));\n"; print FH " end\n"; print FH " end\n" } print FH " join\n" if $n > 1; print FH "\n"; print FH " `uvm_info(get_type_name(), \"Default sequence completed\", UVM_HIGH)\n"; print FH "endtask : body\n"; print FH "\n"; print FH "\n"; print FH "`ifndef UVM_POST_VERSION_1_1\n"; print FH "function uvm_phase ${agent_name}_env_default_seq::get_starting_phase();\n"; print FH " return starting_phase;\n"; print FH "endfunction: get_starting_phase\n"; print FH "\n"; print FH "\n"; print FH "function void ${agent_name}_env_default_seq::set_starting_phase(uvm_phase phase);\n"; print FH " starting_phase = phase;\n"; print FH "endfunction: set_starting_phase\n"; print FH "`endif\n"; print FH "\n"; print FH "\n"; insert_inc_file("", $agent_env_seq_inc{$agent_name}, $agent_env_seq_inc_inline{$agent_name}, "agent_env_seq_inc", $tpl_fname{$agent_name}); print FH "`endif // " . uc($agent_name) . "_ENV_SEQ_LIB_SV\n"; print FH "\n"; close(FH); } sub deal_with_files_f { if ( open( FILESFH, "<", "${dut_path}/files.f") ) { # files.f already exists in DUT directory close(FILESFH); } else { # files.f does not exist, so create files.f in the output directory open( FILESFH, ">", "${dut_tb_path}/files.f"); opendir( DH, $dut_path ) or die "Unable to open DUT directory ${dut_path} when looking for DUT files.f\n"; while (my $file = readdir(DH)) { if ( $file =~ /.*\.sv/ ) { print FILESFH "${file}\n"; } } closedir(DH); close(FILESFH); } } sub gen_questa_script { $dir = $project . "/sim"; open( FH, ">" . $dir . "/compile_questa.do" ) || die "Exiting due to Error: can't open file: compile_questa.do"; print FH "\n"; print FH "file delete -force work\n\n"; print FH "vlib work\n\n"; print FH "#compile the dut code\n"; print FH "set cmd \"vlog -F ../${dut_tb_dir}/files.f\"\n"; print FH "eval \$cmd\n\n"; if($common_pkg_fname) { open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f"; do { print FH "set cmd \"vlog -sv ../${dut_tb_dir}/${common_pkg_fname}\"\n"; print FH "eval \$cmd\n\n"; } unless (grep /$common_pkg_fname/,<FFH>); close FFH; } do { print FH "#compile the register model package\n"; print FH "set cmd \"vlog -sv ../tb/regmodel/${regmodel_file}\"\n"; print FH "eval \$cmd\n\n"; } if $regmodel; print FH "set tb_name $tbname\n"; $incdir = "+incdir+../tb/include "; foreach my $inc_path ( @inc_path_list ) { if ( $inc_path ne "" ) { $incdir .= "+incdir+" . $inc_path . " "; } } if($common_env_pkg_fname) { open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f"; do { print FH "set cmd \"vlog -sv " . $incdir . " ../tb/include/${common_env_pkg_fname}\"\n"; print FH "eval \$cmd\n\n"; } unless (grep /$common_env_pkg_fname/,<FFH>); close FFH; } print FH "set agent_list {\\ \n"; print LOGFILE "env_list=@env_list, agent_list=@agent_list,\n"; foreach my $aname (@stand_alone_agents) { if ( $aname ne "" ) { print FH " $aname \\\n"; } } foreach my $agent (@agent_list) { if ( !grep( /$agent/, @stand_alone_agents ) ) { print FH " $agent \\\n"; } } print FH "}\n"; print FH "foreach ele \$agent_list {\n"; print FH " if {\$ele != \" \"} {\n"; print FH " set cmd \"vlog -sv " . $incdir . "+incdir+../tb/\"\n"; print FH " append cmd \$ele \"/sv ../tb/\" \$ele \"/sv/\" \$ele \"_pkg.sv\ ../tb/\" \$ele \"/sv/\" \$ele \"_if.sv\"\n"; if ( $split_transactors eq "YES") { print FH " append cmd \" ../tb/\" \$ele \"/sv/\" \$ele \"_bfm.sv\"\n"; } print FH " eval \$cmd\n"; print FH " }\n"; print FH "}\n\n"; if ( defined $syosil_scoreboard_src_path ) { print FH "set cmd \"vlog -sv +incdir+../../$syosil_scoreboard_src_path ../../$syosil_scoreboard_src_path/pk_syoscb.sv\"\n"; print FH "eval \$cmd\n\n"; } print FH "set cmd \"vlog -sv " . $incdir . "+incdir+../tb/\"\n"; print FH "append cmd \$tb_name \"/sv ../tb/\" \$tb_name \"/sv/\" \$tb_name \"_pkg.sv\"\n"; print FH "eval \$cmd\n\n"; print FH "set cmd \"vlog -sv " . $incdir . "+incdir+../tb/\"\n"; print FH "append cmd \$tb_name \"_test/sv ../tb/\" \$tb_name \"_test/sv/\" \$tb_name \"_test_pkg.sv\"\n"; print FH "eval \$cmd\n\n"; print FH "set cmd \"vlog -sv -timescale $timeunit/$timeprecision " . $incdir . "+incdir+../tb/\"\n"; print FH "append cmd \$tb_name \"_tb/sv ../tb/\" \$tb_name \"_tb/sv/\" \$tb_name \"_th.sv\"\n"; print FH "eval \$cmd\n\n"; print FH "set cmd \"vlog -sv -timescale $timeunit/$timeprecision " . $incdir . "+incdir+../tb/\"\n"; print FH "append cmd \$tb_name \"_tb/sv ../tb/\" \$tb_name \"_tb/sv/\" \$tb_name \"_tb.sv\"\n"; print FH "eval \$cmd\n\n"; print FH "vsim ${tb_module_name} "; if ( $dual_top eq "YES" ) { print FH "${th_module_name} "; } print FH "+UVM_TESTNAME=${tbname}_test ${uvm_cmdline} -voptargs=+acc -solvefaildebug -uvmcontrol=all -classdebug\n"; print FH "run 0\n"; print FH "#do wave.do\n"; close(FH); ### add execute permissions for script chmod( 0755, $dir . "/compile_questa.do" ); } sub gen_vcs_script { my $dir = $project . "/sim"; my $vcs_opts = "-sverilog +acc +vpi -timescale=$timeunit/$timeprecision -ntb_opts uvm-1.2"; open( FH, ">" . $dir . "/compile_vcs.sh" ) || die "Exiting due to Error: can't open file: compile_vcs.sh"; print FH "#!/bin/sh\n"; print FH "vcs $vcs_opts \\\n"; gen_compile_file_list(); print FH "-R +UVM_TESTNAME=${tbname}_test ${uvm_cmdline} \$* \n"; close(FH); ### add execute permissions for script chmod( 0755, $dir . "/compile_vcs.sh" ); } sub gen_ius_script { my $dir = $project . "/sim"; my $ius_opts = "-vtimescale $timeunit/$timeprecision -uvmhome \${IUS_HOME}/tools/methodology/UVM/CDNS-1.2"; open( FH, ">" . $dir . "/compile_ius.sh" ) || die "Exiting due to Error: can't open file: compile_ius.sh"; print FH "#!/bin/sh\n"; print FH "IUS_HOME=`ncroot`\n"; print FH "irun $ius_opts \\\n"; gen_compile_file_list(); print FH "+UVM_TESTNAME=${tbname}_test ${uvm_cmdline} \$* \n"; close(FH); ### add execute permissions for script chmod( 0755, $dir . "/compile_ius.sh" ); } sub gen_riviera_script { $dir = $project . "/sim"; open( FH, ">" . $dir . "/compile_riviera.do" ) || die "Exiting due to Error: can't open file: compile_riviera.do"; print FH "\n"; print FH "file delete -force work\n\n"; print FH "alib work\n\n"; print FH "# Compile the dut code\n"; print FH "#set cmd \"alog -uvm -F ../${dut_tb_dir}/files.f\" # Previous version using UVM 1.1d\n"; 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"; print FH "eval \$cmd\n\n"; print FH "#set cmd \"alog -uvm \" # Previous version using UVM 1.1d\n"; 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"; if($common_pkg_fname) { open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f"; do { print FH "\n# Compile the common package\n"; print FH "append cmd \" ../${dut_tb_dir}/${common_pkg_fname}\"\n"; } unless (grep /$common_pkg_fname/,<FFH>); close FFH; } do { print FH "\n# Compile the register model package\n"; print FH "append cmd \" ../tb/regmodel/${regmodel_file}\"\n"; } if $regmodel; print FH "\nset tb_name $tbname\n"; $incdir = "+incdir+../tb/include "; foreach my $inc_path ( @inc_path_list ) { if ( $inc_path ne "" ) { $incdir .= "+incdir+" . $inc_path . " "; } } print FH "append cmd \" " . $incdir . "\"\n"; if($common_env_pkg_fname) { open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f"; do { print FH "\n# Compile the common env package\n"; print FH "append cmd \" ../tb/include/${common_env_pkg_fname}\"\n"; } unless (grep /$common_env_pkg_fname/,<FFH>); close FFH; } print FH "\n# Compile the agents\n"; print FH "set agent_list {\\ \n"; print LOGFILE "env_list=@env_list, agent_list=@agent_list,\n"; foreach my $aname (@stand_alone_agents) { if ( $aname ne "" ) { print FH " $aname \\\n"; } } foreach my $agent (@agent_list) { if ( !grep( /$agent/, @stand_alone_agents ) ) { print FH " $agent \\\n"; } } print FH "}\n"; print FH "foreach ele \$agent_list {\n"; print FH " if {\$ele != \" \"} {\n"; print FH " append cmd \" +incdir+../tb/\" \$ele \"/sv ../tb/\" \$ele \"/sv/\" \$ele \"_pkg.sv\ ../tb/\" \$ele \"/sv/\" \$ele \"_if.sv\"\n"; if ( $split_transactors eq "YES") { print FH " append cmd \" ../tb/\" \$ele \"/sv/\" \$ele \"_bfm.sv\"\n"; } print FH " }\n"; print FH "}\n"; if ( defined $syosil_scoreboard_src_path ) { print FH "\n# Compile the Syosil scoreboard\n"; print FH "append cmd \" +incdir+../../$syosil_scoreboard_src_path ../../$syosil_scoreboard_src_path/pk_syoscb.sv\"\n"; } print FH "\n# Compile the test and the modules\n"; print FH "append cmd \" +incdir+../tb/\" \$tb_name \"/sv\"\n"; print FH "append cmd \" ../tb/\" \$tb_name \"/sv/\" \$tb_name \"_pkg.sv\"\n"; print FH "append cmd \" ../tb/\" \$tb_name \"_test/sv/\" \$tb_name \"_test_pkg.sv\"\n"; print FH "append cmd \" ../tb/\" \$tb_name \"_tb/sv/\" \$tb_name \"_th.sv\"\n"; print FH "append cmd \" ../tb/\" \$tb_name \"_tb/sv/\" \$tb_name \"_tb.sv\"\n"; print FH "eval \$cmd\n\n"; print FH "asim ${tb_module_name} "; if ( $dual_top eq "YES" ) { print FH "${th_module_name} "; } print FH "+UVM_TESTNAME=${tbname}_test ${uvm_cmdline} -voptargs=+acc -solvefaildebug -uvmcontrol=all -classdebug\n"; print FH "run -all\n"; print FH "quit\n"; close(FH); ### add execute permissions for script chmod( 0755, $dir . "/compile_riviera.do" ); } sub gen_compile_file_list { my $incdir = "+incdir+../tb/include \\\n"; foreach my $inc_path ( @inc_path_list ) { if ( $inc_path ne "" ) { $incdir .= "+incdir+$inc_path \\\n"; } } # $incdir .= "+incdir+../tb/${tbname}_common/sv \\\n"; foreach my $aname (@stand_alone_agents) { if ( $aname ne "" ) { $incdir .= "+incdir+../tb/${aname}/sv \\\n"; } } foreach my $agent (@agent_list) { if ( !grep( /$agent/, @stand_alone_agents ) ) { $incdir .= "+incdir+../tb/${agent}/sv \\\n"; } } if ( defined $syosil_scoreboard_src_path ) { $incdir .= "+incdir+../../${syosil_scoreboard_src_path}\\\n"; } $incdir .= "+incdir+../tb/${tbname}/sv \\\n"; $incdir .= "+incdir+../tb/${tbname}_test/sv \\\n"; $incdir .= "+incdir+../tb/${tbname}_tb/sv \\\n"; print FH "$incdir"; print FH "-F ../${dut_tb_dir}/files.f \\\n"; if ($common_pkg_fname) { open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f"; print FH "../${dut_tb_dir}/${common_pkg_fname} \\\n" unless (grep /$common_pkg_fname/,<FFH>); close FFH; } if ($common_env_pkg_fname) { open (FFH, "<", "${dut_tb_path}/files.f") || die "Exiting due to Error: can't open file: ${dut_tb_path}/files.f"; print FH "../tb/include/${common_env_pkg_fname} \\\n" unless (grep /$common_env_pkg_fname/,<FFH>); close FFH; } #compile the register model package; print FH "../tb/regmodel/${regmodel_file} \\\n" if $regmodel; #need to compile agents before envs foreach my $aname (@stand_alone_agents) { if ( $aname ne "" ) { print FH "../tb/${aname}/sv/${aname}_pkg.sv \\\n"; print FH "../tb/${aname}/sv/${aname}_if.sv \\\n"; } } foreach my $agent (@agent_list) { if ( !grep( /$agent/, @stand_alone_agents ) ) { print FH "../tb/${agent}/sv/${agent}_pkg.sv \\\n"; print FH "../tb/${agent}/sv/${agent}_if.sv \\\n"; } } if ( $split_transactors eq "YES") { foreach my $agent (@agent_list) { print FH "../tb/${agent}/sv/${agent}_bfm.sv \\\n"; } } if ( defined $syosil_scoreboard_src_path ) { print FH "../../$syosil_scoreboard_src_path/pk_syoscb.sv \\\n"; } print FH "../tb/${tbname}/sv/${tbname}_pkg.sv \\\n"; print FH "../tb/${tbname}_test/sv/${tbname}_test_pkg.sv \\\n"; print FH "../tb/${tbname}_tb/sv/${tbname}_th.sv \\\n"; print FH "../tb/${tbname}_tb/sv/${tbname}_tb.sv \\\n"; } sub print_structure { print "Generated hierarchy of envs and agents:\n"; foreach my $agent_env (@env_list) { print " m_$agent_env\n"; $agent_env =~ /(\w+)_env/; my $agent_name = $1; for ( my $i = 0 ; $i < $number_of_instances{$agent_name} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent_name}); print " m_${agent_name}${suffix}_agent\n"; } foreach my $extra_agent ( @{ $env_agents{$agent_env} } ) { print " m_${extra_agent}_agent\n"; } } foreach my $agent (@top_env_agents) { for ( my $i = 0 ; $i < $number_of_instances{$agent} ; $i++ ) { my $suffix = calc_suffix($i, $number_of_instances{$agent}); print " m_${agent}${suffix}_agent\n"; } } #print "----- ----- ----- ----- -----\n"; #foreach my $inst ( @agent_instance_names ) { # print "Instance name = $inst, agent type = $agent_type_by_inst{$inst}\n"; #} #print "----- ----- ----- ----- -----\n"; }
Go to most recent revision | Compare with Previous | Blame | View Log