📄 generate_ddr_sim_model.pl
字号:
#Copyright (C)2005 Altera Corporation
use europa_all;
use strict;
# Main DDR simulation model.
sub make_ddr_sim_model
{
# No arguments means "Ignore -- I'm being called from make".
if (!@_)
{
# print "\n\tmake_sdram_controller now uses a static".
# " external 'class.ptf'!\n\n";
return 0; # make_class_ptf();
}
# TEW: Get SDRAM's project, Options, etc:
my $project = e_project->new(@_);
my %Options = %{$project->WSA()};
my $WSA = \%Options;
# Grab the module that was created during handle_args.
my $module = $project->top();
# Grab some args to determine how to proceed, like model_base and init_file
$WSA->{is_blank}=($WSA->{sim_Kind} =~ /^blank/i) ? "1" : "0";
$WSA->{is_file} =($WSA->{sim_Kind} =~ /^textfile/i) ? "1" : "0";
my $textfile = $WSA->{sim_Textfile_Info};
#turn bar/foo.srec relative path into an absolute one if needed
my $system_directory = $project->_system_directory();
$textfile =~ s/^(\w+)(\\|\/)/$system_directory$2$1$2/;
#turn foo.srec to absolute path
$textfile =~ s/^(\w+)$/$system_directory\/$1/;
$WSA->{textfile}= $textfile;
# Figure out where our contents are coming from:
$WSA->{Initfile} = $project->_target_module_name() . "_contents.srec";
my $do_generation = $project->system_ptf()->{WIZARD_SCRIPT_ARGUMENTS}{do_build_sim};
# Only generate model if "Simulation. Create simulator..." is ticked.
if ($do_generation == 1) {
print"# Creating memory simulation model for use with ".$project->_target_module_name()."\n";
# We only accept .mif- and .srec-files (or just blankness)
&ribbit ("Memory-initialization files must be either .mif or .srec.\n",
" not '$WSA->{Initfile}'\n")
unless $WSA->{Initfile} =~ /\.(srec|mif)$/i;
# Figure out what language we're generating for
my $lang = $project->system_ptf()->{WIZARD_SCRIPT_ARGUMENTS}{hdl_language};
my $extension;
my $sim_file = $project->get_top_module_name();
my $sim_dat = $project->_target_module_name() . ".dat";
if ($lang =~ /vhd/i ) {
$sim_file .= ".vhd";
$extension = ".vhd";
}
if ($lang =~ /verilog/i) {
$sim_file .= ".v";
$extension = ".v";
}
my @write_lines;
# Add datapath and other files to simulation list
my $sopc_device_family = lc($project->system_ptf()->{WIZARD_SCRIPT_ARGUMENTS}{device_family_id});
my $device_family = lc($WSA->{MEGACORE}{NETLIST_SECTION}{STATIC_SECTION}{PRIVATES}{NAMESPACE}{parameterization}{PRIVATE}{family}{value});
#if ($sopc_device_family ne $device_family) { print "WARNING! The device selected in SOPC Builder (".$sopc_device_family.") does match the DDR SDRAM device (".$device_family.")\n";}
#print "SOPC Builder device family is ".$sopc_device_family."\n";
#print "DDR Megacore device family is ".$device_family."\n";
my $wrapper_name = $project->_target_module_name();
my $quartus_directory = $project->get_quartus_rootdir();
#print "Quartus came from ".$quartus_directory." and device family is $device_family\n";
#print "Wrapper file name is ".$wrapper_name.$extension."\n";
#print "\nOriginal files list = ".$project->module_ptf()->{HDL_INFO}{Simulation_HDL_Files}."\n";
my $magic_proj_dir = "__PROJECT_DIRECTORY__/";
my $datapath_files = "";
# SOPC Builder treats Stratix II & Stratix II GX as different families but we don't...
if ($sopc_device_family eq "stratixiigx") {
$sopc_device_family = "stratixii";
}
# SOPC Builder now treats Stratix & Stratix GX as different families (it didn't used to!) but we don't...
if ($sopc_device_family eq "stratixgx") {
$sopc_device_family = "stratix";
}
# Simulation libraries required
$project->module_ptf()->{HDL_INFO}{Simulation_Library_Names} = "auk_ddr_user_lib,";
#$project->module_ptf()->{HDL_INFO}{Simulation_Library_Names} .= "UNUSED";
$project->module_ptf()->{HDL_INFO}{Simulation_Library_Names} .= "$sopc_device_family";
if ($sopc_device_family eq "cycloneii")
{
$datapath_files .= $quartus_directory."/eda/sim_lib/cycloneii_atoms".$extension.",";
if ($lang =~ /vhd/i) {$datapath_files .= $quartus_directory."/eda/sim_lib/cycloneii_components.vhd,"; }
}
if ($sopc_device_family eq "cyclone")
{
$datapath_files .= $quartus_directory."/eda/sim_lib/cyclone_atoms".$extension.",";
if ($lang =~ /vhd/i) {$datapath_files .= $quartus_directory."/eda/sim_lib/cyclone_components.vhd,"; }
}
# SOPC Builder treats StratixII & StratixII GX as different so we have made the names the same for now
if ($sopc_device_family eq "stratixii")
{
$datapath_files .= $quartus_directory."/eda/sim_lib/stratixii_atoms".$extension.",";
if ($lang =~ /vhd/i) {$datapath_files .= $quartus_directory."/eda/sim_lib/stratixii_components.vhd,"; }
}
# SOPC Builder treats StratixII & StratixII GX as different so we have made the names the same for now
if ($sopc_device_family eq "stratix")
{
$datapath_files .= $quartus_directory."/eda/sim_lib/stratix_atoms".$extension.",";
if ($lang =~ /vhd/i) {$datapath_files .= $quartus_directory."/eda/sim_lib/stratix_components.vhd,"; }
}
# Now add the files needed for the datapath itself
$datapath_files .= $magic_proj_dir.$wrapper_name."_auk_ddr_dqs_group".$extension.",";
$datapath_files .= $magic_proj_dir.$wrapper_name."_auk_ddr_clk_gen".$extension.",";
$datapath_files .= $magic_proj_dir.$wrapper_name."_auk_ddr_datapath".$extension.",";
if ($lang =~ /vhd/i) {$datapath_files .= $magic_proj_dir.$wrapper_name."_auk_ddr_datapath_pack.vhd,";}
$project->module_ptf()->{HDL_INFO}{Simulation_HDL_Files} = $datapath_files.$project->module_ptf()->{HDL_INFO}{Simulation_HDL_Files};
#print "Updated files list = ".$project->module_ptf()->{HDL_INFO}{Simulation_HDL_Files}."\n";
#print "Create libraries called = ".$project->module_ptf()->{HDL_INFO}{Simulation_Library_Names}."\n";
#--------------------------------------------------------
# Create a shortcut to the right bit of the DDR's PTF
my %myshortcut = %{$WSA->{MEGACORE}{NETLIST_SECTION}{STATIC_SECTION}{PRIVATES}{NAMESPACE}{parameterization}};
my $wizard_shortcut = \%myshortcut;
#--------------------------------------------------------
# Work out whether this should be DDR1 or DDR2
my $memtype = $wizard_shortcut->{PRIVATE}{gMEM_TYPE}{value};
#print "This is a ".$memtype." controller\n";
my $mem_pretty_name = "DDR SDRAM";
if ($memtype eq "ddr2_sdram") {$mem_pretty_name = "DDR2 SDRAM";}
my $local_burst_length = $wizard_shortcut->{PRIVATE}{local_burst_length}{value};
# Start building up a simulation-only display string.
@write_lines =
(
"",
"**********************************************************************",
"This testbench includes an SOPC Builder generated Altera memory model:",
"'$sim_file', to simulate accesses to the $mem_pretty_name memory.",
" ",
);
# if ($local_burst_length > 1)
# {
# push @write_lines,(
# "WARNING: The Altera $mem_pretty_name Controller supports Avalon bursts,",
# "but this simulation model does not. If any of the masters in your",
# "SOPC Builder system will issue Avalon bursts, then you ",
# "should use a memory model supplied by your memory vendor. ",
# " ",
# );
# }
push @write_lines,
(
"Initial contents are loaded from the file: ".
"'$sim_dat'."
);
push @write_lines,
("**********************************************************************");
# Convert all lines to e_sim_write objects.
map {$_ = e_sim_write->new({spec_string => $_ . '\\n'})} @write_lines;
# Wrap the simulation-only display string in an e_initial_block, so we
# only see the message once!
if (@write_lines)
{
my $init = e_initial_block->new({
contents => [ @write_lines ],
});
$module->add_contents($init);
} # if (@write_lines)
# sjh WRONG - should get the clock properly!
$WSA->{system_clock_rate} = $project->system_ptf()->{WIZARD_SCRIPT_ARGUMENTS}{clock_freq};
# New style contents generation (a'la OnchipMemoryII -- thanks AaronF)
my $Opt = {name => $project->_target_module_name()};
$project->do_makefile_target_ptf_assignments
(
's1',
['dat', 'sym', ],
$Opt,
);
# Reality checks:
#my $tempclockrate = $project->system_ptf()->{WIZARD_SCRIPT_ARGUMENTS}{clock_freq};
my $clockrate = $wizard_shortcut->{PRIVATE}{clock_speed}{value};
#print "clockrate = $clockrate\n";
my $clockperiod = 1/$clockrate*1000;
#print "clockperiod = $clockperiod\n";
#print "Data width = ".$wizard_shortcut->{PRIVATE}{width}{value}."\n";
#print "Data width2 = ".$WSA->{MEGACORE}{NETLIST_SECTION}{STATIC_SECTION}{PRIVATES}{NAMESPACE}{parameterization}{PRIVATE}{width}{value}."\n";
# SODIMM allows all the same data path widths as the sdram controller
&validate_parameter({
hash => $wizard_shortcut->{PRIVATE}{width},
name => "value",
type => "integer",
allowed => [8, 16, 32, 64],
});
#sjh Don't check these for now
# &validate_parameter({
# hash => $WSA,
# name => "sdram_bank_width",
# type => "integer",
# default => "2",
# allowed => [1, 2],
# });
#sjh Don't check these for now
# # Having a non-integer power of 2 for number of chip selects seems wrong.
# my $num_chipselects = $WSA->{sdram_num_chipselects};
my $num_chipselects = $wizard_shortcut->{PRIVATE}{chipselects}{value};
my $num_chipselect_address_bits = log2($num_chipselects);
# &validate_parameter({
# hash => $WSA,
# name => "sdram_num_chipselects",
# type => "integer",
# allowed => [1, 2, 4, 8],
# });
my $cas_latency = $wizard_shortcut->{PRIVATE}{cas_latency}{value};
#print "CAS latency = $cas_latency\n";
# In the real world, 3 bits of the mode register are used to encode
# cas latency, with code "3'b000" reserved.
&validate_parameter({
hash => $wizard_shortcut->{PRIVATE}{cas_latency},
name => "value",
type => "string",
allowed => ["2.0", "2.5", "3.0", "4.0", "5.0"],
});
my $resynch_phase = $wizard_shortcut->{PRIVATE}{resync_phase}{value};
my $resynch_cycle = $wizard_shortcut->{PRIVATE}{resynch_cycle}{value};
# CAS 2.5 doesn't have any extra handling so we need to act like CAS2 but add a 1/2 cycle delay
my $number_of_lump_delays = 0;
if ($cas_latency eq "2.5")
{
# split total delay in 90 deg segements because we can't set modelsim to use transport delays instead of inertial!
$number_of_lump_delays = 2; # 2 lots of $clockperiod / 4 = 180 deg delay
}
# print "sim delay = cas_latency = $cas_latency, $number_of_lump_delays delays.\n";
#sjh Not needed for DDR
# This setting is hidden from the GUI, but takes affect as a result
# of using the 'preset's...
# FIXME: Our model doesn't care about refresh commands, but we might want
# to indicate via printf/write/$display that they are occuring...
# &validate_parameter({
# hash => $WSA,
# name => "init_refresh_commands",
# type => "integer",
# allowed => [1 .. 8],
# });
# Compute the width of the controller's address (as seen by the Avalon
# bus) from input parameters. SODIMM will address a raw memory array in
# the same way that Avalon accesses the Controller.
# my $addr_width =
# $num_chipselect_address_bits +
# $WSA->{sdram_bank_width} +
# $WSA->{sdram_col_width} +
# $WSA->{sdram_row_width};
my $addr_width = $wizard_shortcut->{PRIVATE}{local_address_width}{value};
my $ba_width = $wizard_shortcut->{PRIVATE}{bankbits}{value};
my $row_width = $wizard_shortcut->{PRIVATE}{rowbits}{value};
my $col_width = $wizard_shortcut->{PRIVATE}{colbits}{value};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -