⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cb_generator.pl

📁 一个用硬件描述语言编写CAN总线控制器的IP
💻 PL
📖 第 1 页 / 共 2 页
字号:
# | file: cb_generator.pl
# |
# | This SOPC Builder Generator program is provided by
# | the Component Builder application. It is copied
# | straight across and is data-driven from its command
# | line arguments and the PTF files referenced.
# |
# | Its purpose is to construct an HDL "wrapper" for
# | a particular instance of a particular SOPC Builder
# | peripheral. This wrapper resolves the instance
# | name and any HDL parameterization.
# |
# +-------------------------------------------



# +-------------------------------------------
# |

use strict;
use format_conversion_utils;
use ptf_parse;
use wiz_utils;
use europa_all;
use run_system_command_utils;

# |
# +-------------------------------------------



# +-------------------------------------------
# |
# | first pass: include all of generator_libarary.pm RIGHT HERE.
# | dvb04.08.02
# | then prune down to actual functionality.
# |
# | TODO: Rewrite this whole file into something readable
# | this is much more confusing than I'm comfortable with. dvb04.
# | (though it does seem to work.)
# |



my $DEBUG_DEFAULT_GEN = 1;

#This is the global hash of arguments passed in by the generator program

my $generator_hr = {
		     wrapper_args => {
				      make_wrapper => 0,
				      top_module_name => "",
				      simulate_hdl => 1,
				      ports => "",
				     },
		     class_ptf_hr => "",
		     module_ptf_hr => "",
		     system_ptf_hr => "",
		     language => "",
		     external_args => "",
		     external_args_hr => "",
		     project_path_widget => "__PROJECT_DIRECTORY__",
		     generator_mode => "silent",
		    };


sub generator_print_verbose
{
  my ($info) = (@_);

  if($generator_hr->{generator_mode} eq "verbose"){
    print("cb_generator.pl: ".$info);
  }
}

sub generator_enable_mode
{
  my ($mode) = (@_);
  $generator_hr->{generator_mode} = $mode;
}

sub generator_get_system_ptf_handle
{ 
  return $generator_hr->{system_ptf_hr};
}

sub generator_get_language
{
  return $generator_hr->{language};
}

sub generator_get_class_ptf_handle
{
  return $generator_hr->{class_ptf_hr};
}

sub default_ribbit
{
  my ($arg) = (@_);
  &ribbit("\n\n--Error: default_gen_lib: $arg\n");  
}


sub _copy_files
{
  my ($dest_dir, $source_dir, @files) = (@_);
  my $function_name;
  
  #validate args
  &default_ribbit("No target dir for function copy_files!")
  unless ($dest_dir ne "");
  
  &default_ribbit("No source dir for function copy_files!")
  unless ($source_dir ne "");

  &default_ribbit("No files for function copy_files!")
  unless (@files != 0);

  
  #check for valid directories
  opendir (SDIR, $source_dir) or 
    &default_ribbit("can't open $source_dir !");
  
  opendir (DDIR, $dest_dir) or
    &default_ribbit("can't open $dest_dir !");
  
  
  foreach my $source_file(@files){
    # |
    # | Separate out the source subdir and the source filename
    # |
    my $source_subdir = "";
    my $source_filename = $source_file;

    if($source_filename =~ /^(.*)\/(.*)$/)  # break on last slash
    {
      $source_subdir = "/$1"; # embed its leading slash, for concatty
      $source_filename = $2;
    }

    my $source_fullpath = "$source_dir$source_subdir/$source_filename";
    my $dest_fullpath = "$dest_dir/$source_filename";

    &Perlcopy($source_fullpath, $dest_fullpath);
    &generator_print_verbose("Copying file: \"$source_fullpath\""
            . " to \"$dest_fullpath\".\n");
  }

  closedir (SDIR);
  closedir (DDIR);
}


sub get_module_wrapper_arg_hash_from_system_ptf_file
{
  my $module_ptf_hr = $generator_hr->{module_ptf_hr};
  
  my @list_of_sections = ("MASTER","SLAVE","PORT_WIRING");
  my @port_list;
  foreach my $section(@list_of_sections){
    my $number = get_child_count($module_ptf_hr, $section);

    for(my $initial=0; $initial < $number; $initial++){
      
      my $interface_section = get_child($module_ptf_hr, $initial, $section);	
      my $interface_section_name = get_data($interface_section);

      my $port_wiring_section;
      if($section ne "PORT_WIRING"){
	$port_wiring_section = 
	  get_child_by_path($module_ptf_hr, $section." ".$interface_section_name."/PORT_WIRING");	
      }else{
	$port_wiring_section =
	  get_child_by_path($module_ptf_hr, $section);
      }
      my $num_ports = get_child_count($port_wiring_section, "PORT");
      foreach(my $port_count = 0; $port_count < $num_ports; $port_count++){
	my $port = get_child($port_wiring_section, $port_count, "PORT");
	
	my %port_info_struct;
	$port_info_struct{name} = get_data($port);
	$port_info_struct{direction} = get_data_by_path($port, "direction");
	$port_info_struct{width} = get_data_by_path($port, "width");
	
	push(@port_list, \%port_info_struct);
	
      }
    }	
  }
  $generator_hr->{wrapper_args}{ports} = \@port_list;
}


sub generator_make_module_wrapper
{
  my ($simulate_hdl, $top_module_name) = (@_);

  &default_ribbit("generator_make_module_wrapper: no arg0 passed in for simulate_hdl\n")
    if($simulate_hdl eq '');

  &default_ribbit("generator_make_module_wrapper: no arg1 passed in for top_module_name\n")
    unless($top_module_name);

  $generator_hr->{wrapper_args}{simulate_hdl} = $simulate_hdl;
  $generator_hr->{wrapper_args}{top_module_name} = $top_module_name;
  $generator_hr->{wrapper_args}{make_wrapper} = 1;

}




# |
# | recognize varous number forms,
# | return 'h0123abcd-ish.
# |
sub turn_anything_into_appropriate_string($$$)
	{
	my ($value,$type,$editable) = (@_);

    return $value if($value =~ /^\"/);   # quoted string: unscathed
    return $value if($type eq "string"); # string: anything is ok
    
    return $value if(!$editable);        # and you know, if you can't change it, keep it!
    
    
	# |
	# | first, convert to a number
	# |
	my $base = 10;
	my $n = $value;
	my $width = 32;
	my $number = 0;
	
	$value = lc($value); # lower case
	
	if($value =~ /^([0-9]*)\'([hbo])(.*)$/)
		{
		# | tick notation
		$width = $1;
		my $baseletter = $2;
		my $digits = $3;
		
		if($baseletter eq "h")
			{
			$base = 16;
			}
		elsif($baseletter eq "b")
			{
			$base = 2;
			}
		elsif($baseletter eq "o") # must be
			{
			$base = 8;
			}
		
		$digits =~ s/[ _-]//g; # crush out dividing value
		
		while(length($digits) > 0)
			{
			my $digit = substr($digits,0,1);
			$digits = substr($digits,1);
			my $digitvalue = hex($digit); # how handy
			$number = $number * $base + $digitvalue;
			}
		}
	elsif($value =~ /^0x(.*)$/)
		{
		$number = hex($1);
		}
	else  # try for decimal
		{
		$number = int(1 * $value);
		}
	
	# |
	# | ok, we have a number. If our target type
	# | is "std_logic_vector(this downto that)"
	# | for tricky VHDL, we
	# | must quote a binary string out of it.
	# |
	
	if($type =~ /^.*\((\d+) downto (\d+)\).*$/)
		{
		my ($high_bit,$low_bit) = ($1,$2);
		my $binary = "";
		for(my $bit = $low_bit; $bit <= $high_bit; $bit++)
			{
			$binary = ($number % 2) . $binary;
			$number = int($number >> 1);
			}
		
		$number = '"' . $binary . '"';
		}
	
	return $number;
	}





sub _generator_make_module_wrapper	
{
  
  my $wrapper_args = $generator_hr->{wrapper_args};
  my $no_black_box = $wrapper_args->{simulate_hdl};
  my $top_module_name = $wrapper_args->{top_module_name};
  my $language = $generator_hr->{language};
  my @external_args = @{$generator_hr->{external_args}};
  my $module_ptf_hr = $generator_hr->{module_ptf_hr};

  ### Build Module
  my $project = e_project->new(@external_args);
  my $top = $project->top();
  
  # add the ports to the system module
  my @ports;
  
  foreach my $port_hash(@{$wrapper_args->{ports}}){
    my $porto = e_port->new({
			     name => $port_hash->{name},
			     width => $port_hash->{width},
			     direction => $port_hash->{direction},
			    });
    push(@ports, $porto);
  }
  $top->add_contents(@ports);
  




    # +----------------------------------------
    # | Get parameters from class.ptf
    # | create @array of parameters, eacho
    # | one like name=>, default=>, type=>,
    # |  
    # | These are the definitions of parameters for
    # | ANY instance of this module; we need to 
    # | have them in the "wrapee" module so that
    # | when the system bus is knitted together
    # | the parameter types can be properly used.
    # |
    # | (as it turns out, verilog doesnt need
    # | them, but vhld does)
    # |
    # | dvb2004


    my @e_hdl_parameters; # list of e_parameters

    my $class_ptf = generator_get_class_ptf_handle();
    my $hdl_parameter_definitions_ptf = get_child_by_path($class_ptf,"CLASS/COMPONENT_BUILDER/HDL_PARAMETERS");

    my $hdl_parameter_count = get_child_count($hdl_parameter_definitions_ptf,"HDL_PARAMETER");


    for(my $i = 0; $i < $hdl_parameter_count; $i++)
        {
        my $a_parameter = get_child($hdl_parameter_definitions_ptf,$i,"HDL_PARAMETER");

        my $boring_name = get_data($a_parameter); # legal guinevere-ized
        my $name = get_data_by_path($a_parameter,"parameter_name"); # original HDL name
        my $default = get_data_by_path($a_parameter,"default_value");
        my $type = get_data_by_path($a_parameter,"type");


        $type = "integer"; # !!!!!
        if($default =~ /^\"(.*)\"$/)
            {
            my $slv_width = length($1);
            my $slv_top = $slv_width - 1;
            my $slv_bottom = 0;
            $type = "std_logic_vector($slv_top downto $slv_bottom)";
            } # !!!!!

        my $a_parameter = e_parameter->new
            ({
            name => $name,
            default => $default,
            type => $type
            });

        push (@e_hdl_parameters,$a_parameter);
        }


    # | and @e_hdl_parameters is used below in the wrappee module
    # +--------------------------------------------

    # +--------------------------------------------
    # | Now, we build a "hdl_parameter_map", which is just
    # | your basic hash table with keys (parameters)
    # | and values (parameter values).
    # |
    # | these are the particular values for this instance.
    # |

    my %hdl_parameter_map;
    my $module_ptf = $generator_hr->{module_ptf_hr};
    my $hdl_parameters_ptf =
            get_child_by_path($module_ptf,"WIZARD_SCRIPT_ARGUMENTS/hdl_parameters");

    my $child_count = get_child_count($hdl_parameters_ptf);

    for(my $i = 0; $i < $child_count; $i++)
        {
        my $a_parameter = get_child($hdl_parameters_ptf,$i);

        my $boring_name = get_name($a_parameter);
        my $value = get_data($a_parameter);

		# refer back to the original HDL name...
        my $parameter_definition_ptf = get_child_by_path($hdl_parameter_definitions_ptf,"HDL_PARAMETER $boring_name");
        my $parameter_name = get_data_by_path($parameter_definition_ptf,"parameter_name");
        my $parameter_type = get_data_by_path($parameter_definition_ptf,"type");
        my $parameter_editable = get_data_by_path($parameter_definition_ptf,"editable");
        
        $value = turn_anything_into_appropriate_string($value,$parameter_type,$parameter_editable);

        $hdl_parameter_map{$parameter_name} = $value;
        }

  my $wrapee_module;
  $wrapee_module = e_module->new({
				 name => $top_module_name,
				 contents =>  [@ports,@e_hdl_parameters],
				 do_black_box => 0,
				 do_ptf => 0,
				 _hdl_generated => 1,
				 _explicitly_empty_module => 1,
				});

  $top->add_contents (
		      e_instance->new({
				       module => $wrapee_module,
                       parameter_map => \%hdl_parameter_map
				      }),
		     );
  
  $project->top()->do_ptf(0);
  $project->do_write_ptf(0);
  
  
  my $module_file = $project->_target_module_name().".v";
  $module_file = $project->_target_module_name().".vhd"
    if($language eq "vhdl");

  $module_file = $generator_hr->{project_path_widget}."/".$module_file;
  &generator_set_files_in_system_ptf("Synthesis_HDL_Files", ($module_file));
  $project->output();


  # if you don't want a simulation model, you don't get a simulation model
  if($no_black_box eq "0")
  {
    my $black_project = e_project->new(@external_args);
    $black_project->_target_module_name($top_module_name);
    my $black_top = $black_project->top();



    $black_top->add_contents(@ports);
    my $black_top_instance;
    $black_top_instance = e_module->new({
				   name => $wrapper_args->{top_module_name}."_bb",
				   contents =>  [@ports],
				   do_black_box => 1,
				   do_ptf => 0,
				   _hdl_generated => 0,
				   _explicitly_empty_module => 1,
				  });
    
    $black_top->add_contents (
			e_instance->new({
					 module => $black_top_instance,
					}),
		       );




    $black_project->top()->do_ptf(0);
    $black_project->do_write_ptf(0);

    my $black_module_file = $black_project->_target_module_name().".v";
    $black_module_file = $black_project->_target_module_name().".vhd"
      if($language eq "vhdl");


    $black_module_file = $generator_hr->{project_path_widget}."/".$black_module_file;
    &generator_set_files_in_system_ptf("Simulation_HDL_Files", ($black_module_file));

#    &set_data_by_path($module_ptf_hr, "HDL_INFO/Simulation_HDL_Files", $black_module_file);


    $black_project->output();
  }

}

####
# Args: $file_type : "synthesis", "synthesis_only", "simulation"
#       @file_list   :  an array of files.  This list of files is assumed to be relative to the
#                       component's directory


my $decoder_ring_hr = {
			quartus_only => {
					 copy => 1,
					 copy_to => "project",
					 ptf_set => 0,
					},
			simulation_only => {
					    copy => 1,
					    copy_to => "simulation",
					    ptf_set => 1,
					    ptf_section => "Simulation_HDL_Files",
					   },
			simulation_and_quartus => {
						   copy => 1,
						   copy_to => "project",
						   ptf_set => 1,
						   ptf_section => "Synthesis_HDL_Files",
						  }, 
		       precompiled_simulation_files => {
							copy => 0,
							ptf_set => 1,
							ptf_section => "Precompiled_Simulation_Library_Files",
						       },
		      };




sub generator_copy_files_and_set_system_ptf
{
  my ($hdl_section, @file_list) = (@_);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -