#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
#
|
#
|
# ############################################################################
|
# ############################################################################
|
#
|
#
|
# vcd2vec.pl
|
# vcd2vec.pl
|
#
|
#
|
# $Id: vcd2vec.pl 295 2009-04-01 19:32:48Z arniml $
|
# $Id: vcd2vec.pl 295 2009-04-01 19:32:48Z arniml $
|
#
|
#
|
# Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
|
# Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
|
#
|
#
|
# All rights reserved
|
# All rights reserved
|
#
|
#
|
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
# the Free Software Foundation; either version 2 of the License, or
|
# the Free Software Foundation; either version 2 of the License, or
|
# (at your option) any later version. See also the file COPYING which
|
# (at your option) any later version. See also the file COPYING which
|
# came with this application.
|
# came with this application.
|
#
|
#
|
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
#
|
#
|
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
#
|
#
|
# ############################################################################
|
# ############################################################################
|
#
|
#
|
# Purpose:
|
# Purpose:
|
# ========
|
# ========
|
#
|
#
|
# Converts a VCD-file to a vector file.
|
# Converts a VCD-file to a vector file.
|
#
|
#
|
# Reads VCD from STDIN and writes the resulting vector stream to STDOUT.
|
# Reads VCD from STDIN and writes the resulting vector stream to STDOUT.
|
# vcd2vec.pl -s <signals file> [-i] [-h]
|
# vcd2vec.pl -s <signals file> [-i] [-h]
|
# -s : Name of the file containing the signals for vector output
|
# -s : Name of the file containing the signals for vector output
|
# -i : Read initial state from VCD (given with $dumpvars)
|
# -i : Read initial state from VCD (given with $dumpvars)
|
# -h : Print this help
|
# -h : Print this help
|
#
|
#
|
|
|
|
|
use strict;
|
use strict;
|
|
|
use Getopt::Std;
|
use Getopt::Std;
|
|
|
|
|
my $time_unit = 'ns';
|
my $time_unit = 'ns';
|
|
|
sub print_usage {
|
sub print_usage {
|
print <<EOU;
|
print <<EOU;
|
Reads VCD from STDIN and writes the resulting vector stream to STDOUT.
|
Reads VCD from STDIN and writes the resulting vector stream to STDOUT.
|
Usage:
|
Usage:
|
vcd2vec.pl -s <signals file> [-i] [-h]
|
vcd2vec.pl -s <signals file> [-i] [-h]
|
-s : Name of the file containing the signals for vector output
|
-s : Name of the file containing the signals for vector output
|
-i : Read initial state from VCD (given with \$dumpvars)
|
-i : Read initial state from VCD (given with \$dumpvars)
|
-h : Print this help
|
-h : Print this help
|
EOU
|
EOU
|
}
|
}
|
|
|
sub print_index {
|
sub print_index {
|
my $index = shift;
|
my $index = shift;
|
my ($tok, $desc);
|
my ($tok, $desc);
|
|
|
while (($tok, $desc) = each %{$index}) {
|
while (($tok, $desc) = each %{$index}) {
|
print("Token $tok:\n");
|
print("Token $tok:\n");
|
print(" $desc->{'name'}\n");
|
print(" $desc->{'name'}\n");
|
print(" $desc->{'pos'}\n");
|
print(" $desc->{'pos'}\n");
|
}
|
}
|
}
|
}
|
|
|
sub dump_state {
|
sub dump_state {
|
my ($state, $time, $dump_signals) = @_;
|
my ($state, $time, $dump_signals) = @_;
|
my $signal;
|
my $signal;
|
|
|
print("${time}>");
|
print("${time}>");
|
foreach $signal (@{$dump_signals}) {
|
foreach $signal (@{$dump_signals}) {
|
if (exists($state->{$signal})) {
|
if (exists($state->{$signal})) {
|
print(" ".$state->{$signal});
|
print(" ".$state->{$signal});
|
} else {
|
} else {
|
print(STDERR "Error: Signal '$signal' not included in VCD!\n");
|
print(STDERR "Error: Signal '$signal' not included in VCD!\n");
|
}
|
}
|
}
|
}
|
print("\n");
|
print("\n");
|
}
|
}
|
|
|
sub read_scope {
|
sub read_scope {
|
my $scope = shift;
|
my $scope = shift;
|
my $index = shift;
|
my $index = shift;
|
my $pos = shift;
|
my $pos = shift;
|
my ($token, $base, $extension);
|
my ($token, $base, $extension);
|
my $ipt;
|
my $ipt;
|
|
|
print("Processing scope '$scope'\n");
|
print("Processing scope '$scope'\n");
|
|
|
while (<STDIN>) {
|
while (<STDIN>) {
|
last if (/^\$upscope/);
|
last if (/^\$upscope/);
|
|
|
last if (/^\$enddefinitions/);
|
last if (/^\$enddefinitions/);
|
|
|
if (/^\$var +\S+ +\S+ +(\S+) +(\S+) +(([^\$]\S*)|\$end)/) {
|
if (/^\$var +\S+ +\S+ +(\S+) +(\S+) +(([^\$]\S*)|\$end)/) {
|
$token = $1;
|
$token = $1;
|
$base = $2;
|
$base = $2;
|
|
|
$extension = defined($4) ? $4 : '';
|
$extension = defined($4) ? $4 : '';
|
$extension =~ s/[\[\]]//g;
|
$extension =~ s/[\[\]]//g;
|
|
|
$index->{$token} = {};
|
$index->{$token} = {};
|
$ipt = $index->{$token};
|
$ipt = $index->{$token};
|
$ipt->{'name'} = "$scope.$base$extension";
|
$ipt->{'name'} = "$scope.$base$extension";
|
$ipt->{'pos'} = $$pos++;
|
$ipt->{'pos'} = $$pos++;
|
|
|
print("Appended ".$ipt->{'name'}."\n");
|
print("Appended ".$ipt->{'name'}."\n");
|
}
|
}
|
|
|
if (/^\$scope +\S+ +(\S+)/) {
|
if (/^\$scope +\S+ +(\S+)/) {
|
read_scope("$scope.$1", $index, $pos);
|
read_scope("$scope.$1", $index, $pos);
|
}
|
}
|
|
|
if (/^\$timescale/) {
|
if (/^\$timescale/) {
|
$_ = <STDIN>;
|
$_ = <STDIN>;
|
if (/^\s*1(\S+)/) {
|
if (/^\s*1(\S+)/) {
|
$time_unit = $1;
|
$time_unit = $1;
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
my %options;
|
my %options;
|
my %index;
|
my %index;
|
my %state;
|
my %state;
|
my ($i, $time, $pos);
|
my ($i, $time, $pos);
|
my $index;
|
my $index;
|
my $token;
|
my $token;
|
my ($ipt, $val);
|
my ($ipt, $val);
|
my ($tok, $desc);
|
my ($tok, $desc);
|
my $signal;
|
my $signal;
|
my $initial_states = 0;
|
my $initial_states = 0;
|
local *SIGNALS_FILE;
|
local *SIGNALS_FILE;
|
|
|
my @dump_signals;
|
my @dump_signals;
|
|
|
# process command line options
|
# process command line options
|
if (!getopts('s:ih', \%options)) {
|
if (!getopts('s:ih', \%options)) {
|
print_usage();
|
print_usage();
|
exit(1);
|
exit(1);
|
}
|
}
|
|
|
if (exists($options{'h'})) {
|
if (exists($options{'h'})) {
|
print_usage();
|
print_usage();
|
exit(0);
|
exit(0);
|
}
|
}
|
|
|
if (exists($options{'i'})) {
|
if (exists($options{'i'})) {
|
$initial_states = 1;
|
$initial_states = 1;
|
}
|
}
|
|
|
if (exists($options{'s'})) {
|
if (exists($options{'s'})) {
|
} else {
|
} else {
|
print(STDERR "File with signal names is required!\n");
|
print(STDERR "File with signal names is required!\n");
|
print_usage();
|
print_usage();
|
exit(1);
|
exit(1);
|
}
|
}
|
|
|
|
|
##############################################################################
|
##############################################################################
|
# Read signals file
|
# Read signals file
|
#
|
#
|
if (!open(SIGNALS_FILE, "<$options{'s'}")) {
|
if (!open(SIGNALS_FILE, "<$options{'s'}")) {
|
print(STDERR "Cannot read signals file '$options{'s'}'!\n");
|
print(STDERR "Cannot read signals file '$options{'s'}'!\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
|
|
@dump_signals = <SIGNALS_FILE>;
|
@dump_signals = <SIGNALS_FILE>;
|
close(SIGNALS_FILE);
|
close(SIGNALS_FILE);
|
chomp(@dump_signals);
|
chomp(@dump_signals);
|
|
|
|
|
# parse header
|
# parse header
|
$index = {};
|
$index = {};
|
$pos = 0;
|
$pos = 0;
|
read_scope("", $index, \$pos);
|
read_scope("", $index, \$pos);
|
|
|
|
|
if ($initial_states) {
|
if ($initial_states) {
|
# read initial state
|
# read initial state
|
while (<STDIN>) { last if (/^\$dumpvars/) }
|
while (<STDIN>) { last if (/^\$dumpvars/) }
|
while (<STDIN>) {
|
while (<STDIN>) {
|
last if (/^\$end/);
|
last if (/^\$end/);
|
if (/^(.)(\S+)/) {
|
if (/^(.)(\S+)/) {
|
$val = $1;
|
$val = $1;
|
$token = $2;
|
$token = $2;
|
$state{$index->{$token}->{'name'}} = $val;
|
$state{$index->{$token}->{'name'}} = $val;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
$time = '0';
|
$time = '0';
|
|
|
print("time:");
|
print("time:");
|
foreach $signal (@dump_signals) {
|
foreach $signal (@dump_signals) {
|
print(" $signal");
|
print(" $signal");
|
}
|
}
|
print("\n");
|
print("\n");
|
|
|
# now read all state changes
|
# now read all state changes
|
while (<STDIN>) {
|
while (<STDIN>) {
|
if (/^#(\d+)/) {
|
if (/^#(\d+)/) {
|
if ($1 != 0) {
|
if ($1 != 0) {
|
# dump previous state
|
# dump previous state
|
dump_state(\%state, $time, \@dump_signals);
|
dump_state(\%state, $time, \@dump_signals);
|
}
|
}
|
$time = $1;
|
$time = $1;
|
next;
|
next;
|
} else {
|
} else {
|
if (/^(\S)(\S+)$/) {
|
if (/^(\S)(\S+)$/) {
|
$val = $1;
|
$val = $1;
|
$token = $2;
|
$token = $2;
|
$state{$index->{$token}->{'name'}} = $val;
|
$state{$index->{$token}->{'name'}} = $val;
|
}
|
}
|
|
|
if (/^(\S+) (\S+)$/) {
|
if (/^(\S+) (\S+)$/) {
|
$val = $1;
|
$val = $1;
|
$token = $2;
|
$token = $2;
|
$state{$index->{$token}->{'name'}} = $val;
|
$state{$index->{$token}->{'name'}} = $val;
|
}
|
}
|
}
|
}
|
|
|
}
|
}
|
|
|
# final dump
|
# final dump
|
dump_state(\%state, $time, \@dump_signals);
|
dump_state(\%state, $time, \@dump_signals);
|
|
|
0;
|
0;
|
|
|