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

Subversion Repositories veristruct

[/] [veristruct/] [trunk/] [Verilog/] [Veristruct/] [Struct.pm] - Rev 6

Compare with Previous | Blame | View Log

#######################################################################
# 
# This file is a part of the Rachael SPARC project accessible at
# https://www.rachaelsparc.org. Unless otherwise noted code is released
# under the Lesser GPL (LGPL) available at http://www.gnu.org.
#
# Copyright (c) 2005: 
#   Michael Cowell
#
# Rachael SPARC is based heavily upon the LEON SPARC microprocessor
# released by Gaisler Research, at http://www.gaisler.com, under the
# LGPL. Much of the architectural work on Rachael was done by g2
# Microsystems. Contact michael.cowell@g2microsystems.com for more
# information.
#
#######################################################################
# $Id: Struct.pm,v 1.1 2008-10-10 21:13:56 julius Exp $
# $URL: $ 
# $Rev: $
# $Author: julius $
######################################################################
#
# This file is the struct module of the Veristruct Perl program.
#
# This class supports structs. It can parse struct definitons, and
# print out various struct representations.
#
######################################################################
 
use Verilog::Veristruct::Structlib;
 
package Verilog::Veristruct::Struct;
 
our $debug = 1;
 
sub new {
    $classobject = {};
    bless($classobject);
    local %struct_hash;
    $classobject->{"struct_hash"} = \%struct_hash;
    return $classobject;
} 
 
# Parses a string (that should be a valid struct definition)
sub parse {
    my ($self, $struct_string, $string_position) = @_;
 
    # Set search to begin at the relevant point in the buffer
    pos($$struct_string) = $string_position;
 
    # Find struct name
    if ($$struct_string !~ m/\G\s*struct\s+(\w+)\s*{/gis) {
	print "Couldn't find pattern: 'struct name {' in struct block.\n";
	return;
    }
 
    $self->{"name"} = $1;
 
    # Find all elements  
    while ($$struct_string =~ m/\G\s*(\w+)\s+(\w+)/gcs) {
 
	# Pull out the back-references
	my $elem_type = $1; my $elem_name = $2;
 
	if ($elem_type eq "wire") {
	    if ($$struct_string =~ m/\G\s*(\S+)\s*;/gcs) {
		# Ranged wire
		my $range = $1;
		$self->{"struct_hash"}->{$elem_name} = {};
		$self->{"struct_hash"}->{$elem_name}->{"type"} = "vector";
		$self->{"struct_hash"}->{$elem_name}->{"range"} = $range;
	    } elsif ($$struct_string =~ m/\G\s*;/gcs) {
		$self->{"struct_hash"}->{$elem_name} = {};
		$self->{"struct_hash"}->{$elem_name}->{"type"} = "wire";
	    } else {
		print "Invalid syntax in struct file - semicolon not",
		" found after element definition.";
		return;
	    }
	} elsif ($elem_type eq "signed") {
	    if ($$struct_string =~ m/\G\s*(\S+)\s*;/gcs) {
		# Ranged wire
		my $range = $1;
		$self->{"struct_hash"}->{$elem_name} = {};
		$self->{"struct_hash"}->{$elem_name}->{"type"} = "svector";
		$self->{"struct_hash"}->{$elem_name}->{"range"} = $range;
	    } elsif ($$struct_string =~ m/\G\s*;/gcs) {
		$self->{"struct_hash"}->{$elem_name} = {};
		$self->{"struct_hash"}->{$elem_name}->{"type"} = "signed";
	    } else {
		print "Invalid syntax in struct file - semicolon not",
		" found after element definition.";
		return;
	    }
	}  else {
	    $self->{"struct_hash"}->{$elem_name} = {};
	    $self->{"struct_hash"}->{$elem_name}->{"type"} = "struct";
	    $self->{"struct_hash"}->{$elem_name}->{"struct"} = $elem_type;
 
            # Check for closing brace
	    if ($$struct_string !~ m/\G\s*;/gcs) {
		print "Invalid syntax in struct file - semicolon not",
		" found after element definition.\n";
		print "Rest of buffer is: ",
		substr($$struct_string, pos($$struct_string)), "\n";
		return;
	    }
	}
 
    }
 
    # Find closing brace
    if ($$struct_string !~ m/\G\s*};/gcs) {
	print "Couldn't find closing brace in struct defn.\n";
	return;
    }
 
    # Push position back to method that called us
    return pos($$struct_string);
}
 
# For debugging:
sub print_elem_info {
    my ($self) = @_;
    foreach $elem_name (keys (%{$self->{"struct_hash"}})) {
	print "  $elem_name: ";
	my $type = $self->{"struct_hash"}->{$elem_name}->{"type"};
	if (($type eq "wire") or ($type eq "signed")) {
	    print "wire\n";
	} elsif (($type eq "vector") or ($type eq "svector")) {
	    my $range = $self->{"struct_hash"}->{$elem_name}->{"range"};
	    print "vector, range is $range\n";
	} elsif ($type eq "struct") {
	    my $struct = $self->{"struct_hash"}->{$elem_name}->{"struct"};
	    print "nested struct of type $struct\n";
	}
    }
}
 
sub get_name {
    my ($self) = @_;
    return $self->{"name"};
}
 
# Function to return a valid portlist string
sub get_portlist_string {
    my ($self, $inst_name, $range, $sep, $structlib) = @_;
    my $buffer; my $seperator = "";
 
    foreach $elem (keys (%{$self->{"struct_hash"}})) {
	my $type = $self->{"struct_hash"}->{$elem}->{"type"};
	if (($type eq "wire") or ($type eq "vector") or
	    ($type eq "signed") or ($type eq "svector")) {
	    $buffer .= $seperator . $inst_name . "__" . $elem . $range;
	    $seperator = $sep." ";
	} else {
	    # nested struct
	    my $struct = $self->{"struct_hash"}->{$elem}->{"struct"};
	    if (!($structlib->{"structs"}->{$struct})) {
		print "Nested struct named $struct_name in module port list",
		" undefined. Failure.\n";
		return;
	    }
	    $buffer .= $seperator .
		$structlib->{"structs"}->{$struct}->get_portlist_string(
		($inst_name . "__" . $elem), $range, $sep, $structlib);
	    $seperator = $sep." ";
	}
    }
 
    return $buffer;
}
 
# Function to return a named portlist string
sub get_named_portlist_string {
    my ($self, $local_name, $port_name, $local_range, $structlib) = @_;
    my $buffer; my $seperator = "";
 
    foreach $elem (keys (%{$self->{"struct_hash"}})) {
	my $type = $self->{"struct_hash"}->{$elem}->{"type"};
	if (($type eq "wire") or ($type eq "vector") or
	    ($type eq "signed") or ($type eq "svector")) {
	    $buffer .= $seperator . "." . $port_name . "__" . $elem . 
		" (" . $local_name . "__" . $elem . $local_range. ")";
	    $seperator = ", ";
	} else {
	    # nested struct
	    my $struct = $self->{"struct_hash"}->{$elem}->{"struct"};
	    if (!($structlib->{"structs"}->{$struct})) {
		print "Nested struct named $struct_name in module port list",
		" undefined. Failure.\n";
		return;
	    }
	    $buffer .= $seperator .
		$structlib->{"structs"}->{$struct}->
		get_named_portlist_string(($local_name . "__" . $elem), 
		  ($port_name . "__" . $elem), $local_range, $structlib);
	    $seperator = ", ";
	}
    }
 
    return $buffer;
}
 
# Function to get a whole struct assignment
sub get_decl_struct_assign {
    my ($self, $procedural, $left, $lrange, 
	$right, $rrange, $operator, $structlib) = @_;
    my $buffer;
 
    if ($procedural) {$assign = "";} else {$assign = "assign ";}
 
    foreach $elem (keys (%{$self->{"struct_hash"}})) {
	my $type = $self->{"struct_hash"}->{$elem}->{"type"};
	if (($type eq "wire") or ($type eq "vector") or
	    ($type eq "signed") or ($type eq "svector")) {
	    $buffer.="${assign}${left}__$elem$lrange $operator ".
	    "${right}__$elem$rrange; ";
	} else {
	    # nested struct
	    my $struct = $self->{"struct_hash"}->{$elem}->{"struct"};
	    if (!($structlib->{"structs"}->{$struct})) {
		print "Nested struct named $struct in assignment",
		" undefined. Failure.\n";
		return;
	    }
	    $buffer .= 
		$structlib->{"structs"}->{$struct}->get_decl_struct_assign(
		$procedural, ($left."__".$elem), $lrange, ($right."__".$elem), 
		    $rrange, $operator, $structlib);
	    $seperator = ", ";
	}
    }
 
    return $buffer;
}
 
# Function to return a struct declaration:
sub get_scalar_decl_string {
    my ($self, $inst, $context, $structlib) = @_;
    my $buffer;
    foreach $elem (keys (%{$self->{"struct_hash"}})) {
	my $type = $self->{"struct_hash"}->{$elem}->{"type"};
	if ($type eq "wire") {
	    $buffer .= "$context ${inst}__${elem}; ";
	} elsif ($type eq "vector") {
	    my $range = $self->{"struct_hash"}->{$elem}->{"range"};
	    $buffer .= "$context $range ${inst}__${elem}; ";
	} elsif ($type eq "signed") {
	    $buffer .= "$context signed ${inst}__${elem}; ";
	} elsif ($type eq "svector") {
	    my $range = $self->{"struct_hash"}->{$elem}->{"range"};
	    $buffer .= "$context signed $range ${inst}__${elem}; ";
	} elsif ($type eq "struct") {
	    my $struct = $self->{"struct_hash"}->{$elem}->{"struct"};
	    $buffer .= $structlib->{"structs"}->{$struct}->
		get_scalar_decl_string(($inst."__".$elem), $context, 
				       $structlib);
	}
    }
    return $buffer;
}
 
# Function to return a struct declaration:
sub get_vector_decl_string {
    my ($self, $inst, $context, $range, $structlib) = @_;
    my $buffer;
    foreach $elem (keys (%{$self->{"struct_hash"}})) {
	my $type = $self->{"struct_hash"}->{$elem}->{"type"};
	if ($type eq "wire") {
	    $buffer .= "$context ${range}${inst}__${elem}; ";
	} elsif ($type eq "vector") {
	    my $elem_range = $self->{"struct_hash"}->{$elem}->{"range"};
	    $buffer .= "$context $elem_range${inst}__${elem}$range; ";
	} elsif ($type eq "signed") {
	    $buffer .= "$context signed ${range}${inst}__${elem}; ";
	} elsif ($type eq "svector") {
	    my $elem_range = $self->{"struct_hash"}->{$elem}->{"range"};
	    $buffer .= "$context signed $elem_range${inst}__${elem}$erange; ";
	} elsif ($type eq "struct") {
	    my $struct = $self->{"struct_hash"}->{$elem}->{"struct"};
	    $buffer .= $structlib->{"structs"}->{$struct}->
		get_scalar_decl_string(($inst."__".$elem), $context, 
				       $structlib);
	}
    }
    return $buffer;
}
 
# Get elem range string
sub get_elem_range_string {
    my ($self, $elem_string, $structlib) = @_;
    if ($elem_string =~ m/(\w+)\.(.*)/) {
	$struct = $self->{"struct_hash"}->{${1}}->{"struct"};
	$struct or die
	    "${1} not a valid struct.";
	return $structlib->{"structs"}->{$struct}->get_elem_range_string($2,$structlib);
    }
    return $self->{"struct_hash"}->{$elem_string}->{"range"};
}
 
# Retuns a series of assignments (that copies one struct to another)
sub get_struct_assign {
    my ($self, $linst, $lrange, $rinst, $rrange, $op, $seperator, $structlib, $recurs) = @_;
    my $buffer;
    foreach $elem (keys (%{$self->{"struct_hash"}})) {
	my $type = $self->{"struct_hash"}->{$elem}->{"type"};
	if ($type eq "wire"  or $type eq "vector") {
	    $buffer .= "${linst}__${elem}${lrange}${op}${rinst}__${elem}".
		"${rrange}${seperator}";
	    #print "Buffer now $buffer\n";
	} elsif ($type eq "struct") {
	    my $struct = $self->{"struct_hash"}->{$elem}->{"struct"};
	    $buffer .= $structlib->{"structs"}->{$struct}->
		get_struct_assign(($linst."__".$elem), $lrange, ($rinst."__".$elem),
				  $rrange, $op, $seperator, $structlib, 1);
	    #print "Buffer now $buffer\n";
	}
    }
    # Have to remove the last seperator if we're not recursive
    if (!($recurs)) {
	#print "Recurs is $recurs\n";
	$buffer =~ s/(.*)${seperator}/$1/;
    }
    return $buffer;
}
 
1;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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