Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / perl-5.8.0 / lib / site_perl / 5.8.0 / Midas / MMU / SunSectionAttrs.pm
# -*- perl -*-
package Midas::MMU::SunSectionAttrs;
use strict;
use Midas::Command;
use Midas::AttrBlock;
use Midas::Globals;
use Midas::Error;
use Midas::MMU::TTEFormat;
use TRELoad 'BitFieldTie';
use base qw(Midas::AttrBlock::MapAttrs);
use fields (
qw(
pa bypass
tsbonly notsb uninitialized
tte_size_ptr
),
(
# Hard-code MMU type because 'use fields' directive needs
# to happen at compile-time
keys %{ get_union_tte_field_hash('ultra2') }
)
);
our @Settable = (
qw(
pa bypass
tsbonly notsb uninitialized
tte_size_ptr
),
);
our %Settable = map {$_ => 1} Midas::MMU::SunSectionAttrs->settable();
our %FieldSizes =
(
tsbonly => 1,
notsb => 1,
bypass => 1,
uninitialized => 1,
tte_size_ptr => 3,
);
###############################################################################
sub new {
my $this = shift;
my %args = @_;
unless (ref $this) {
$this = fields::new($this);
}
$this->SUPER::new();
$this->{settable} = \%Settable;
foreach my $key (keys %args) {
$this->{$key} = $args{$key};
}
return $this;
}
###############################################################################
sub set_defaults {
my $this = shift;
$this->SUPER::set_defaults();
$this->{bypass} = 0 unless defined $this->{bypass};
$this->{tsbonly} = 0 unless defined $this->{tsbonly};
$this->{notsb} = 0 unless defined $this->{notsb};
$this->{uninitialized} = 0 unless defined $this->{uninitialized};
$this->{tte_size} = 0 unless defined $this->{tte_size};
}
###############################################################################
sub get_field_size_hash {
my $this = shift;
my $sizes = $this->SUPER::get_field_size_hash();
foreach my $field (keys %FieldSizes) {
$sizes->{$field} = $FieldSizes{$field};
}
return $sizes;
}
###############################################################################
sub sanity_check {
my $this = shift;
my @messages = $this->SUPER::sanity_check();
my $name = $this->get_section_name();
my $fline = $this->get_fline();
if($this->{uninitialized} && $this->{tsbonly}) {
my $message = "Section '$name' redundantly specifies both tsbonly and ".
"uninitialized.\n at $fline\n";
push @messages, { message => $message, code => M_ATTRSYNTAX };
}
return @messages;
}
###############################################################################
sub settable {
my $this = shift;
my @settable = $this->SUPER::settable();
push @settable, @Settable;
return @settable;
}
###############################################################################
sub skip_image {
my $this = shift;
return 1 if $this->{tsbonly} || $this->{uninitialized};
return 0;
}
###############################################################################
sub set_attr {
my $this = shift;
my $attr = shift;
my $val = shift;
my $lcattr = lc $attr;
if (exists $MapAttr_FieldMax{$lcattr}) {
my $width = $MapAttr_FieldWidth{$lcattr};
$this->attr_fatal("Attribute \"$attr\" set to non-numeric value: ".
"\"$val\"\n", M_NOTNUM)
unless $val =~ /^\s*(0[xX])?[\da-fA-F]+\s*$/;
my $val_bf = string2bf($val, 64);
if(not ref $val_bf) {
$this->attr_fatal("Value \"$val\" is not a ${width}-bit hex number:\n".
"$val_bf",
M_NOTNUM);
}
my $range_bf = $MapAttr_FieldMax{$lcattr};
if($val_bf->ucompare($range_bf) >= 0) {
$this->attr_fatal("Value \"$val\" is out of range for ".
"${width}-bit field '$attr'.", M_OUTOFRANGE);
}
$val = $val_bf->extract($width-1, 0);
}
$this->SUPER::set_attr($attr => $val);
}
###############################################################################
sub get_data_addr_bits {
my $this = shift;
return (39, 13);
}
###############################################################################
sub get_tag {
my $this = shift;
my $force_ctx_zero = shift;
$this->attr_fatal("Getting tag for unmapped section.\n", M_CODE)
unless $this->is_mapped();
my $addr = '0';
my $tag = tte_hash_to_tsb_tag($this->{mmutype},
$CONFIG{tsbtagfmt}, $this,
$addr, $force_ctx_zero);
fatal "Combination of MMU type $this->{mmutype} and TSB tag format ".
"$CONFIG{tsbtagfmt}\n is not legal\n", M_ATTRSYNTAX unless defined $tag;
return $tag;
}
###############################################################################
sub legal_page_bits {
my $this = shift;
return (0 .. 7);
}
###############################################################################
sub get_pa_bf {
my $this = shift;
return unless $this->is_mapped();
return unless exists $this->{pa} and defined $this->{pa};
my $pa = string2bf($this->{pa}, $PASIZE);
if(not ref $pa) {
$this->attr_fatal("Cannot interpret PA \"$this->{pa}\":\n$pa\n", M_NOTNUM);
}
return $pa;
}
###############################################################################
sub is_mapped {
my $this = shift;
return 1 unless $this->{bypass};
return;
}
###############################################################################
sub get_data {
my $this = shift;
my $tsb = shift;
my $ttefmt = $tsb->get_ttefmt();
$this->attr_fatal("Getting data for unmapped section.\n", M_CODE)
unless $this->is_mapped();
$this->attr_fatal("Trying to generate TTE data in illegal format ".
"'$ttefmt'\n", M_ATTRSYNTAX) unless
is_good_format_for_mmu($this->{mmutype}, $ttefmt);
my $addr = 0;
my $data = tte_hash_to_tsb_data($this->{mmutype},
$ttefmt, $this, $addr);
fatal "Combination of MMU type $this->{mmutype} and TTE format $ttefmt ".
" is not legal\n", M_ATTRSYNTAX unless defined $data;
return $data;
}
##############################################################################
sub write_goldfinger_mmu_params {
my $this = shift;
my $ofh = shift;
my $tsblist = $this->get_tsb_list();
print $ofh " no_end_range_check = 1;\n" if $this->{uninitialized};
print $ofh " PA_EQ_VA;\n" if not $this->is_mapped();
print $ofh " RA_EQ_VA;\n" if $this->{bypass};
if(@$tsblist) {
my ($tag_bit_hi, $tag_bit_lo) = $this->get_tag_addr_bits();
my ($tte_tag_bit_hi, $tte_tag_bit_lo) = $this->get_tte_tag_addr_bits();
my ($data_bit_hi, $data_bit_lo) = $this->get_data_addr_bits();
foreach my $tsbname (@$tsblist) {
my $tsb = $STATE->{tsbs}{$tsbname};
my $data = $this->get_data($tsb);
my $sizeptr;
if(defined $this->{tte_size_ptr}) {
$sizeptr = $this->{tte_size_ptr};
} elsif(defined $tsb->page_size()) {
$sizeptr = $tsb->page_size();
} else {
$sizeptr = $this->{tte_size};
}
my $pagesize = 8192 * (8 ** $sizeptr);
my $size3 = 3 * $sizeptr;
my $va_ind_hi = 21+$size3;
my $va_ind_lo = 13+$size3;
my $force_ctx_zero = $tsb->is_force_ctx_zero();
my $tag = $this->get_tag($force_ctx_zero);
print $ofh " BLOCK_TSB $tsbname\n";
print $ofh " page_size = $pagesize;\n";
print $ofh " va_index_bits = $va_ind_hi : $va_ind_lo;\n";
print $ofh " tag_addr_bits = $tag_bit_hi : $tag_bit_lo;\n";
print $ofh " tte_tag_addr_bits = $tte_tag_bit_hi : $tte_tag_bit_lo;\n";
print $ofh " data_addr_bits = $data_bit_hi : $data_bit_lo;\n";
print $ofh " tag_base = 0x$tag;\n";
print $ofh " data_base = 0x$data;\n";
print $ofh " END BLOCK_TSB\n";
}
}
}
###############################################################################
sub get_tag_addr_bits {
my $this = shift;
if($CONFIG{tsbtagfmt} eq 'tagtarget') {
return (41, 0);
} else {
return (63, 13);
}
}
##############################################################################
sub get_tte_tag_addr_bits {
my $this = shift;
if($CONFIG{tsbtagfmt} eq 'tagtarget') {
return (63, 22);
} else {
return (63, 13);
}
}
###############################################################################
###############################################################################
{
package Midas::MMU::SunHyperAttrs;
use Midas::Globals;
use Midas::Error;
use Midas::Command;
use base qw(Midas::MMU::SunSectionAttrs);
use fields qw(ra hypervisor );
our @Settable = (qw(ra hypervisor));
our %Settable = map { $_ => 1} Midas::MMU::SunHyperAttrs->settable();
our %FieldSizes =
(
hypervisor => 1,
);
############################################################################
sub new {
my $this = shift;
my %args = @_;
unless (ref $this) {
$this = fields::new($this);
}
$this->{settable} = \%Settable;
foreach my $key (keys %args) {
$this->{$key} = $args{$key};
}
return $this;
}
############################################################################
sub set_defaults {
my $this = shift;
$this->SUPER::set_defaults();
$this->{hypervisor} = 0 unless defined $this->{hypervisor};
}
#############################################################################
sub settable {
my $this = shift;
my @settable = $this->SUPER::settable();
push @settable, @Settable;
return @settable;
}
#############################################################################
sub get_field_size_hash {
my $this = shift;
my $sizes = $this->SUPER::get_field_size_hash();
foreach my $field (keys %FieldSizes) {
$sizes->{$field} = $FieldSizes{$field};
}
return $sizes;
}
############################################################################
sub get_ra_bf {
my $this = shift;
return unless $this->is_mapped();
return unless exists $this->{ra} and defined $this->{ra};
my $ra = BitFieldTie->new($RASIZE, $this->{ra});
if(not ref $ra) {
$this->attr_fatal("Cannot interpret RA \"$this->{ra}\":\n$ra",
M_NOTNUM);
}
return $ra;
}
############################################################################
sub sanity_check {
my $this = shift;
my @messages = $this->SUPER::sanity_check();
my $name = $this->get_section_name();
my $fline = $this->get_fline();
if($this->{hypervisor}) {
if(defined $this->{ra}) {
my $message = "Section '$name' hypervisor block has RA defined\n".
" at $fline\n";
push @messages, { message => $message, code => M_ATTRSYNTAX };
}
if(defined $this->{pa}) {
my $message = "Section '$name' hypervisor block has PA defined\n".
" at $fline\n";
push @messages, { message => $message, code => M_ATTRSYNTAX };
}
if($this->{bypass}) {
my $message = "Section '$name' hypervisor block has bypass defined\n".
" at $fline\n";
push @messages, { message => $message, code => M_ATTRSYNTAX };
}
my @settable = keys %MapAttr_Settable;
foreach my $settable (@settable) {
if(($settable =~ /^tte/ or $settable =~ /^tsb/ )
and $this->{has_set}{$settable})
{
my $message = "Section '$name' hypervisor block sets tte attr ".
"\"$settable\"\n".
" at $fline\n";
push @messages, { message => $message, code => M_ATTRSYNTAX };
}
}
} else {
if(not $CONFIG{allow_illegal_page_sizes}) {
if(not grep /^$this->{tte_size}$/, $this->legal_page_bits()) {
my $message = "Section '$name' has illegal page size bits ".
"'$this->{tte_size}'\n".
"Not allowed unles -allow_illegal_page_sizses is used\n".
" at $fline\n";
push @messages, { message => $message, code => M_ILLEGALPARAM };
}
if(defined $this->{tte_size_ptr}) {
if(not grep /^$this->{tte_size_ptr}$/, $this->legal_page_bits()) {
my $message = "Section '$name' has illegal page size ptr bits ".
"'$this->{tte_size_ptr}'\n".
"Not allowed unles -allow_illegal_page_sizses is used\n".
" at $fline\n";
push @messages, { message => $message, code => M_ILLEGALPARAM };
}
}
}
if(not defined $this->{pa} and not $this->skip_image()) {
my $message = "Section '$name' non-hv block has no PA defined\n".
" at $fline\n";
push @messages, { message => $message, code => M_ATTRSYNTAX };
}
if(not $this->{bypass} and not defined $this->{ra} and
not $this->{notsb})
{
my $message = "Section '$name' is not bypass or hypervisor and\n".
"does not define RA.\n at $fline\n";
push @messages, { message => $message, code => M_ATTRSYNTAX };
}
if($this->{bypass} and defined $this->{ra}) {
my $message = "Section '$name' defines both bypass and RA.\n".
" at $fline\n";
push @messages, { message => $message, code => M_ATTRSYNTAX };
}
my $num_tsbs = @{ $this->{tsbnames} };
if(not $num_tsbs and not $this->{notsb}) {
my $message = "Section '$name' non-hv block defines no TSBs\n".
" at $fline\n";
push @messages, { message => $message, code => M_ATTRSYNTAX };
}
if($num_tsbs and $this->{notsb}) {
my $message = "Section '$name' defined $num_tsbs TSB(s) and notsb\n".
" at $fline\n";
push @messages, { message => $message, code => M_ATTRSYNTAX };
}
if(defined $this->{va}) {
my $va_bf = string2bf($this->{va}, $VASIZE);
if(not ref $va_bf) {
my $message = "Section '$name' VA is not a number:\n$va_bf\n".
" at $fline\n";
push @messages, { message => $message, code => M_NOTNUM };
} else {
}
}
if(defined $this->{ra}) {
my $ra_bf = string2bf($this->{ra}, $RASIZE);
if(not ref $ra_bf) {
my $message = "Section '$name' RA is not a number:\n$ra_bf.\n".
" at $fline\n";
push @messages, { message => $message, code => M_NOTNUM };
} else {
}
}
if(defined $this->{pa}) {
my $pa_bf = string2bf($this->{pa}, $PASIZE);
if(not ref $pa_bf) {
my $message = "Section '$name' PA is not a number:\n$pa_bf.\n".
" at $fline\n";
push @messages, { message => $message, code => M_NOTNUM };
} else {
}
}
}
return @messages;
}
###########################################################################
sub is_mapped {
my $this = shift;
return 1 unless $this->{hypervisor};
return;
}
###########################################################################
}
###############################################################################
###############################################################################
1;