| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# |
|
2
|
|
|
|
|
|
|
# This file is part of the Perlilog project. |
|
3
|
|
|
|
|
|
|
# |
|
4
|
|
|
|
|
|
|
# Copyright (C) 2003, Eli Billauer |
|
5
|
|
|
|
|
|
|
# |
|
6
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify |
|
7
|
|
|
|
|
|
|
# it under the terms of the GNU General Public License as published by |
|
8
|
|
|
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or |
|
9
|
|
|
|
|
|
|
# (at your option) any later version. |
|
10
|
|
|
|
|
|
|
# |
|
11
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful, |
|
12
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14
|
|
|
|
|
|
|
# GNU General Public License for more details. |
|
15
|
|
|
|
|
|
|
# |
|
16
|
|
|
|
|
|
|
# You should have received a copy of the GNU General Public License |
|
17
|
|
|
|
|
|
|
# along with this program; if not, write to the Free Software |
|
18
|
|
|
|
|
|
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
19
|
|
|
|
|
|
|
# |
|
20
|
|
|
|
|
|
|
# A copy of the license can be found in a file named "licence.txt", at the |
|
21
|
|
|
|
|
|
|
# root directory of this project. |
|
22
|
|
|
|
|
|
|
# |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
${__PACKAGE__.'::errorcrawl'}='system'; |
|
25
|
|
|
|
|
|
|
sub who { |
|
26
|
0
|
|
|
0
|
|
0
|
return "The Global Object"; |
|
27
|
|
|
|
|
|
|
} |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub new { |
|
30
|
1
|
|
|
1
|
|
1
|
my $this = shift; |
|
31
|
1
|
|
|
|
|
6
|
my $self = $this->SUPER::new(@_); |
|
32
|
|
|
|
|
|
|
|
|
33
|
1
|
|
|
|
|
3
|
my $name = $self->get('name'); |
|
34
|
1
|
50
|
|
|
|
3
|
puke("The \'global\' class can generate an object only with the name \'globalobject\'". |
|
35
|
|
|
|
|
|
|
" and not \'$name\'\n") unless ($name eq 'globalobject'); |
|
36
|
|
|
|
|
|
|
|
|
37
|
1
|
|
|
|
|
2
|
return $self; |
|
38
|
|
|
|
|
|
|
} |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub complete { |
|
41
|
0
|
|
|
0
|
|
|
my $self = shift; |
|
42
|
0
|
|
|
|
|
|
my $dir=$self->get('filesdir'); |
|
43
|
0
|
0
|
|
|
|
|
blow("The \'filesdir\' property was not set for ".$self->who()."\n") |
|
44
|
|
|
|
|
|
|
unless ($dir); |
|
45
|
0
|
0
|
|
|
|
|
mkdir $dir, 0777 unless -e $dir; |
|
46
|
0
|
0
|
|
|
|
|
opendir(DIR,$dir) || blow("Failed to open $dir as a directory\n"); |
|
47
|
0
|
|
|
|
|
|
my @A=readdir(DIR); |
|
48
|
0
|
|
|
|
|
|
closedir(DIR); |
|
49
|
0
|
|
|
|
|
|
foreach (grep /[^.]/, @A) { |
|
50
|
0
|
|
|
|
|
|
unlink "$dir/$_"; |
|
51
|
|
|
|
|
|
|
} |
|
52
|
|
|
|
|
|
|
} |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# NOTE: execute does not allow extra methods or objects to be |
|
55
|
|
|
|
|
|
|
# added once started. |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
sub execute { |
|
58
|
0
|
|
|
0
|
|
|
my $global = shift; # We're the global object, aren't we? |
|
59
|
0
|
0
|
|
|
|
|
puke("The execute method was not run from the global object\n") |
|
60
|
|
|
|
|
|
|
unless ($global == $global->globalobj()); |
|
61
|
0
|
|
|
|
|
|
my $system = $global -> get('system'); |
|
62
|
0
|
|
|
|
|
|
my @methods = $system -> get('methods'); |
|
63
|
0
|
|
|
|
|
|
my @objects = ($global -> get('beginobjects'), |
|
64
|
|
|
|
|
|
|
$global -> get('objects'), |
|
65
|
|
|
|
|
|
|
$global -> get('endobjects')); |
|
66
|
0
|
|
|
|
|
|
my ($method, $object); |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# Note that the global object sneaks in first here |
|
69
|
0
|
|
|
|
|
|
@methods = grep { defined } @methods; |
|
|
0
|
|
|
|
|
|
|
|
70
|
0
|
|
|
|
|
|
@objects = grep { defined } ($global, @objects); |
|
|
0
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
|
|
72
|
0
|
|
|
|
|
|
foreach $method (@methods) { |
|
73
|
0
|
|
|
|
|
|
foreach $object (@objects) { |
|
74
|
0
|
|
|
|
|
|
$object->$method(); |
|
75
|
|
|
|
|
|
|
} |
|
76
|
0
|
0
|
|
|
|
|
last if ($Perlilog::wrongflag); |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub constreset { |
|
81
|
0
|
|
|
0
|
|
|
my ($self, $ID, $type) = @_; |
|
82
|
|
|
|
|
|
|
wrong ("Reset of unknown type \'$type\'") |
|
83
|
0
|
0
|
|
|
|
|
unless grep {$type eq $_} qw(sync negsync async negasync); |
|
|
0
|
|
|
|
|
|
|
|
84
|
0
|
0
|
|
|
|
|
wrong ("Unproper ID \'$ID\' given for reset signal\n") |
|
85
|
|
|
|
|
|
|
unless (defined $Perlilog::VARS[$ID]); |
|
86
|
|
|
|
|
|
|
# $self is global object! |
|
87
|
0
|
|
|
|
|
|
$self->const('reset_type', $type); |
|
88
|
0
|
|
|
|
|
|
$self->const('reset_ID', $ID); |
|
89
|
|
|
|
|
|
|
} |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub instantiate { |
|
92
|
0
|
|
|
0
|
|
|
my $self = shift; |
|
93
|
0
|
|
|
|
|
|
$self->SUPER::instantiate(@_); |
|
94
|
0
|
|
|
|
|
|
my ($i, $ID, $drive, $obj, $var, $type, $parent); |
|
95
|
0
|
|
|
|
|
|
my ($from, $start, $to, $next, $f, $t, $toname); |
|
96
|
0
|
|
|
|
|
|
my ($fv, $tv, $dim, $nv, $nID, $tmp, $wf, $hashref); |
|
97
|
|
|
|
|
|
|
|
|
98
|
0
|
|
|
|
|
|
my %eqvars; |
|
99
|
0
|
|
|
|
|
|
my @eq; |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# Type conversion hashes |
|
102
|
0
|
|
|
|
|
|
my %toin=('input' => 'input', |
|
103
|
|
|
|
|
|
|
'wire' => 'input', |
|
104
|
|
|
|
|
|
|
'inout' => 'inout', |
|
105
|
|
|
|
|
|
|
'output'=> 'inout'); |
|
106
|
0
|
|
|
|
|
|
my %toout=('output' => 'output', |
|
107
|
|
|
|
|
|
|
'reg' => 'outreg', |
|
108
|
|
|
|
|
|
|
'outreg' => 'outreg', |
|
109
|
|
|
|
|
|
|
'wire' => 'output', |
|
110
|
|
|
|
|
|
|
'inout' => 'inout', |
|
111
|
|
|
|
|
|
|
'input' => 'inout'); |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# We begin with triggering off tree studies. |
|
114
|
0
|
|
|
|
|
|
foreach $i (values %Perlilog::objects) { |
|
115
|
0
|
0
|
|
|
|
|
next unless (defined $i->get('inshash')); # Only Verilog objects... |
|
116
|
0
|
0
|
|
|
|
|
next if (ref $i->get('parent')); # Only "root" objects... |
|
117
|
0
|
|
|
|
|
|
$i->treestudy; |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# Now we collapse the EQVARS list to the minimal number |
|
121
|
|
|
|
|
|
|
# of distinct lists. Note that the hash keys are the |
|
122
|
|
|
|
|
|
|
# string representation of the reference, and only |
|
123
|
|
|
|
|
|
|
# functions as a unique representation of the reference. |
|
124
|
|
|
|
|
|
|
# The value points to the index in EQVARS, which makes |
|
125
|
|
|
|
|
|
|
# is possible to retrieve the EQVARS list again. |
|
126
|
|
|
|
|
|
|
# We loop in reverse order, so that the value will represent |
|
127
|
|
|
|
|
|
|
# the variable in the cluster that was defined earliest. |
|
128
|
|
|
|
|
|
|
|
|
129
|
0
|
|
|
|
|
|
my $imax = $#Perlilog::EQVARS; |
|
130
|
0
|
|
|
|
|
|
for ($i=$imax; $i>=0; $i--) { |
|
131
|
0
|
0
|
|
|
|
|
next unless (ref $Perlilog::EQVARS[$i]); |
|
132
|
0
|
|
|
|
|
|
$eqvars{$Perlilog::EQVARS[$i]}=$i; |
|
133
|
|
|
|
|
|
|
} |
|
134
|
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
my @in; |
|
136
|
|
|
|
|
|
|
my @out; |
|
137
|
0
|
|
|
|
|
|
my @zout; |
|
138
|
0
|
|
|
|
|
|
my %where; |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
# This little subroutine will help up make nice error messages. |
|
141
|
|
|
|
|
|
|
# Note that it runs in the current scope. |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
my $s = sub { |
|
144
|
0
|
|
|
0
|
|
|
my $r = "These are the variables involved:\n"; |
|
145
|
0
|
0
|
|
|
|
|
if (@out) { |
|
146
|
0
|
|
|
|
|
|
$r.="Driving variables:\n"; |
|
147
|
0
|
|
|
|
|
|
foreach (@out) |
|
148
|
0
|
|
|
|
|
|
{ $r.=" Variable ".$self->varwho($_)."\n"; } |
|
149
|
|
|
|
|
|
|
} |
|
150
|
0
|
0
|
|
|
|
|
if (@zout) { |
|
151
|
0
|
|
|
|
|
|
$r.="Weakly driving variables:\n"; |
|
152
|
0
|
|
|
|
|
|
foreach (@zout) |
|
153
|
0
|
|
|
|
|
|
{ $r.=" Variable ".$self->varwho($_)."\n"; } |
|
154
|
|
|
|
|
|
|
} |
|
155
|
0
|
0
|
|
|
|
|
if (@in) { |
|
156
|
0
|
|
|
|
|
|
$r.="Driven variables:\n"; |
|
157
|
0
|
|
|
|
|
|
foreach (@in) |
|
158
|
0
|
|
|
|
|
|
{ $r.=" Variable ".$self->varwho($_)."\n"; } |
|
159
|
|
|
|
|
|
|
} |
|
160
|
0
|
|
|
|
|
|
return $r; |
|
161
|
0
|
|
|
|
|
|
}; |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# This is the main loop. Each $i is a variable cluster that |
|
164
|
|
|
|
|
|
|
# needs to be interconnected. |
|
165
|
|
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
|
foreach $i (sort values %eqvars) { |
|
167
|
|
|
|
|
|
|
|
|
168
|
0
|
|
|
|
|
|
my @ids=@{$Perlilog::EQVARS[$i]}; # Get a local copy. The original may change |
|
|
0
|
|
|
|
|
|
|
|
169
|
0
|
0
|
|
|
|
|
next unless ($#ids>0); # No hassle with unconnected variables |
|
170
|
|
|
|
|
|
|
|
|
171
|
0
|
|
|
|
|
|
@in=(); @out=(); @zout=(); |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
172
|
0
|
|
|
|
|
|
%where=(); |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
# We now distribute the variables to the respective lists. We |
|
175
|
|
|
|
|
|
|
# also set up the %where hash that tells us the names of the |
|
176
|
|
|
|
|
|
|
# variables in the objects, if they exist. Again, the keys |
|
177
|
|
|
|
|
|
|
# are not real references but string representations, but it's |
|
178
|
|
|
|
|
|
|
# good enough for looking up. |
|
179
|
|
|
|
|
|
|
IDLOOP: |
|
180
|
0
|
|
|
|
|
|
foreach $ID (sort @ids) { |
|
181
|
0
|
|
|
|
|
|
($obj, $var) = @{$Perlilog::VARS[$ID]}; |
|
|
0
|
|
|
|
|
|
|
|
182
|
0
|
|
|
|
|
|
$drive = $obj->get(['vars', $var, 'drive']); |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# If $where{$obj} is already defined, it means we have two |
|
185
|
|
|
|
|
|
|
# equal variables in the same module. This is handled quite |
|
186
|
|
|
|
|
|
|
# gracefully as long as they don't happen to be both zouts. |
|
187
|
|
|
|
|
|
|
# For the case when they are both zouts, by make a nonstrength- |
|
188
|
|
|
|
|
|
|
# reducing transistor connecting, as would an inout connection, |
|
189
|
|
|
|
|
|
|
# and don't deal with the new variable any more. |
|
190
|
|
|
|
|
|
|
|
|
191
|
0
|
0
|
|
|
|
|
if (defined $where{$obj}) { |
|
192
|
0
|
0
|
|
|
|
|
if ($drive eq 'zout') { |
|
193
|
0
|
0
|
|
|
|
|
if ($obj->get(['vars', $where{$obj}, 'drive']) eq 'zout') { |
|
194
|
|
|
|
|
|
|
# Horrors! Two zouts in the same module! |
|
195
|
0
|
|
|
|
|
|
my $tranins = $obj->suggestins('PL_tran'); |
|
196
|
0
|
|
|
|
|
|
$obj->addins($tranins, 'detached'); |
|
197
|
|
|
|
|
|
|
wrong("Failed to handle bidirectional variable \'".$var."\' in ".$obj->who. |
|
198
|
|
|
|
|
|
|
" because the Verilog is static\n") |
|
199
|
0
|
0
|
|
|
|
|
unless ($obj->append(" tran $tranins ($var, ".$where{$obj}.");\n")); |
|
200
|
0
|
|
|
|
|
|
next IDLOOP; # Don't register this variable. It's already handled |
|
201
|
|
|
|
|
|
|
} else { |
|
202
|
|
|
|
|
|
|
# The existing variable wasn't a zout, but we'll set $where{$obj} to this |
|
203
|
|
|
|
|
|
|
# variable, so we won't miss a zout clash in the future... |
|
204
|
0
|
|
|
|
|
|
$where{$obj} = $var; |
|
205
|
|
|
|
|
|
|
} |
|
206
|
|
|
|
|
|
|
} |
|
207
|
|
|
|
|
|
|
# Note that we do nothing if this is not a zout case. We let the previously |
|
208
|
|
|
|
|
|
|
# registered variable persist. |
|
209
|
|
|
|
|
|
|
} else { |
|
210
|
0
|
|
|
|
|
|
$where{$obj} = $var; # This is just the normal case. A first-timer |
|
211
|
|
|
|
|
|
|
} |
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
# We put the variable in the right list, according to "drive" |
|
214
|
|
|
|
|
|
|
|
|
215
|
0
|
0
|
|
|
|
|
if ($drive eq 'in') { push @in, $ID; } |
|
|
0
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
216
|
0
|
|
|
|
|
|
elsif ($drive eq 'out') { push @out, $ID; } |
|
217
|
0
|
|
|
|
|
|
elsif ($drive eq 'zout') { push @zout, $ID; } |
|
218
|
|
|
|
|
|
|
elsif ($drive eq 'via') { |
|
219
|
0
|
|
|
|
|
|
wrong("Variable ".$self->varwho($ID). |
|
220
|
|
|
|
|
|
|
" was of drive-type \'via\' (System error?)\n"); |
|
221
|
|
|
|
|
|
|
} else { |
|
222
|
0
|
|
|
|
|
|
wrong("Variable ".$self->varwho($ID). |
|
223
|
|
|
|
|
|
|
" is of unknown drive-type \'$drive\'\n"); |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
} |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# Now we complain if things aren't so good... |
|
228
|
0
|
0
|
0
|
|
|
|
if (($#out<0) && ($#zout<0)) { |
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
229
|
0
|
|
|
|
|
|
wrong("No driving variable in cluster\n".&$s); |
|
230
|
|
|
|
|
|
|
} elsif ($#out>0) { |
|
231
|
0
|
|
|
|
|
|
wrong("More than one exclusively driving variable in cluster\n".&$s); |
|
232
|
|
|
|
|
|
|
} elsif (($#out==0) && ($#zout>=0)) { |
|
233
|
0
|
|
|
|
|
|
wrong("Exclusiveness of driving variable was offended by weakly driven variables\n".&$s); |
|
234
|
|
|
|
|
|
|
} |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
# Now we draw lines from every driving variable to every |
|
237
|
|
|
|
|
|
|
# driven variable. |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
FLOOP: # The "from" loop -- driving variables |
|
240
|
0
|
|
|
|
|
|
foreach $f ((sort @out), (sort @zout)) { |
|
241
|
0
|
|
|
|
|
|
($start, $fv) = @{$Perlilog::VARS[$f]}; |
|
|
0
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
TLOOP: # The "to" loop -- driven variables |
|
243
|
0
|
|
|
|
|
|
foreach $t ((sort @in), (sort @zout)) { |
|
244
|
0
|
0
|
|
|
|
|
next TLOOP if ($t == $f); |
|
245
|
0
|
|
|
|
|
|
($to, $tv) = @{$Perlilog::VARS[$t]}; |
|
|
0
|
|
|
|
|
|
|
|
246
|
0
|
|
|
|
|
|
$from = $start; |
|
247
|
0
|
|
|
|
|
|
$toname = $to->get('name'); |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
# If we happen to start and end at the same object, |
|
250
|
|
|
|
|
|
|
# why hassle? Just make an internal assignment. But |
|
251
|
|
|
|
|
|
|
# alas, the current object may not allow its Verilog |
|
252
|
|
|
|
|
|
|
# content to change, in which case append() fails. |
|
253
|
|
|
|
|
|
|
# In that case we simply go on, which will cause |
|
254
|
|
|
|
|
|
|
# a walk-up to the parent and back (good). |
|
255
|
|
|
|
|
|
|
next TLOOP |
|
256
|
0
|
0
|
0
|
|
|
|
if (($start == $to) && |
|
257
|
|
|
|
|
|
|
($start->append(" assign $tv = $fv;\n"))); |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
# OK, now we come to SLOOP: The walking around loop. |
|
260
|
|
|
|
|
|
|
# We travel our way to $to. treestudy() earlier |
|
261
|
|
|
|
|
|
|
# promised to take us there, so we trust it and |
|
262
|
|
|
|
|
|
|
# run the loop until we reach the place. |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
SLOOP: |
|
265
|
0
|
|
|
|
|
|
while (1) { |
|
266
|
|
|
|
|
|
|
# We fetch the next object to walk to |
|
267
|
0
|
|
|
|
|
|
$next = ${$from->get('treepath')}{$toname}; |
|
|
0
|
|
|
|
|
|
|
|
268
|
0
|
0
|
|
|
|
|
unless (ref $next) { |
|
269
|
0
|
|
|
|
|
|
wrong("No path found between variables ".$self->varwho($f). |
|
270
|
|
|
|
|
|
|
" and ".$self->varwho($t)."\n"); |
|
271
|
0
|
|
|
|
|
|
next TLOOP; |
|
272
|
|
|
|
|
|
|
} |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# Now the world splits in two: Either we went from child |
|
275
|
|
|
|
|
|
|
# to parent, or the opposite way. Anyhow, this takes |
|
276
|
|
|
|
|
|
|
# opposite treatment, since we always create the inputs and |
|
277
|
|
|
|
|
|
|
# outputs on the child, whereas the parent gets a "wire" at |
|
278
|
|
|
|
|
|
|
# most. |
|
279
|
|
|
|
|
|
|
|
|
280
|
0
|
|
|
|
|
|
$parent = $next->get('parent'); |
|
281
|
0
|
0
|
0
|
|
|
|
if (defined ($parent) && ($parent == $from)) { |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# This is the parent to child walk part: |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
# Get the variable name an $next's object. If we happen to |
|
286
|
|
|
|
|
|
|
# have reached our destination, take $tv. This is because |
|
287
|
|
|
|
|
|
|
# if there are two input variables in the same object, |
|
288
|
|
|
|
|
|
|
# only one will be represented in $where{$next} |
|
289
|
|
|
|
|
|
|
|
|
290
|
0
|
0
|
|
|
|
|
$nv = ($next==$to) ? $tv : $where{$next}; |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
# If $nv is not defined, it means that object currently |
|
293
|
|
|
|
|
|
|
# has no access to the variable. We create a via. |
|
294
|
0
|
0
|
|
|
|
|
unless (defined $nv) { |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
# Now we want to set the name nicely. If the current object |
|
297
|
|
|
|
|
|
|
# has the 'viasource' (list) property set, we scan through the objects |
|
298
|
|
|
|
|
|
|
# from which we may borrow the name. Only non-via variables |
|
299
|
|
|
|
|
|
|
# may donate names. |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
VIALOOP1: |
|
302
|
0
|
|
|
|
|
|
foreach my $source ($next->get('viasource')) { |
|
303
|
0
|
0
|
0
|
|
|
|
if ((defined $where{$source}) && |
|
304
|
|
|
|
|
|
|
($source->get(['vars',$where{$source},'drive']) ne 'via')) { |
|
305
|
0
|
|
|
|
|
|
$nv = $next->suggestvar($where{$source}); # This is a good source! |
|
306
|
0
|
|
|
|
|
|
last VIALOOP1; # No more search! |
|
307
|
|
|
|
|
|
|
} |
|
308
|
|
|
|
|
|
|
} |
|
309
|
|
|
|
|
|
|
|
|
310
|
0
|
0
|
|
|
|
|
$nv = $next->suggestvar($fv.'_via') # Make _via |
|
311
|
|
|
|
|
|
|
unless (defined $nv); |
|
312
|
|
|
|
|
|
|
|
|
313
|
0
|
|
|
|
|
|
$nID = $next->addvar($nv, 'wire', 'via'); |
|
314
|
0
|
|
|
|
|
|
$next->attach($f, $nID); # This will also get the 'dim' property right |
|
315
|
0
|
|
|
|
|
|
$where{$next}=$nv; # Register it, so we won't do this again |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
# Now we change the variable's type if needed. |
|
319
|
0
|
|
|
|
|
|
$tmp = $toin{$next->get(['vars',$nv,'type'])}; |
|
320
|
0
|
0
|
|
|
|
|
blow("Expected a variable convertable to input/inout, got ". |
|
321
|
|
|
|
|
|
|
"variable \'$nv\' of type \'".$next->get(['vars',$nv,'type'])."\' on ". |
|
322
|
|
|
|
|
|
|
$next->who."\n") |
|
323
|
|
|
|
|
|
|
unless (defined $tmp); |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
# We can't change variable types of static objects. Be sure. |
|
326
|
|
|
|
|
|
|
|
|
327
|
0
|
0
|
|
|
|
|
if ($next->get('static')) { |
|
328
|
0
|
0
|
|
|
|
|
wrong("Attempted to change the variable type of $nv to $tmp in ". |
|
329
|
|
|
|
|
|
|
$next->who()." but it is a static Verilog object\n") |
|
330
|
|
|
|
|
|
|
unless ($next->get(['vars',$nv,'type']) eq $tmp) |
|
331
|
|
|
|
|
|
|
} else { |
|
332
|
0
|
|
|
|
|
|
$next->set(['vars',$nv,'type'], $tmp); |
|
333
|
|
|
|
|
|
|
} |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
# And finally, we register the connection in 'inshash'. We are not |
|
336
|
|
|
|
|
|
|
# worried about if the entry is already set, because it will always |
|
337
|
|
|
|
|
|
|
# be set to the same value, $where{$from} |
|
338
|
|
|
|
|
|
|
|
|
339
|
0
|
|
|
|
|
|
$hashref = $next->get('inshash'); |
|
340
|
0
|
|
|
|
|
|
${$hashref}{$nv}=$where{$from}; |
|
|
0
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
} else { |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
# This is the child to parent walk part: (quite similar) |
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
# Get the variable name an $next's object. If we happen to |
|
347
|
|
|
|
|
|
|
# have reached our destination, take $tv. This is because |
|
348
|
|
|
|
|
|
|
# if there are two input variables in the same object, |
|
349
|
|
|
|
|
|
|
# only one will be represented in $where{$next} |
|
350
|
|
|
|
|
|
|
|
|
351
|
0
|
0
|
|
|
|
|
$nv = ($next==$to) ? $tv : $where{$next}; |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
# If $nv is not defined, it means that object currently |
|
354
|
|
|
|
|
|
|
# has no access to the variable. We create a via. |
|
355
|
0
|
0
|
|
|
|
|
unless (defined $nv) { |
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# Now we want to set the name nicely. If the current object |
|
358
|
|
|
|
|
|
|
# has the 'viasource' (list) property set, we scan through the objects |
|
359
|
|
|
|
|
|
|
# from which we may borrow the name. Only non-via variables |
|
360
|
|
|
|
|
|
|
# may donate names. |
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
VIALOOP2: |
|
363
|
0
|
|
|
|
|
|
foreach my $source ($next->get('viasource')) { |
|
364
|
0
|
0
|
0
|
|
|
|
if ((defined $where{$source}) && |
|
365
|
|
|
|
|
|
|
($source->get(['vars',$where{$source},'drive']) ne 'via')) { |
|
366
|
0
|
|
|
|
|
|
$nv = $next->suggestvar($where{$source}); # This is a good source! |
|
367
|
0
|
|
|
|
|
|
last VIALOOP2; # No more search! |
|
368
|
|
|
|
|
|
|
} |
|
369
|
|
|
|
|
|
|
} |
|
370
|
|
|
|
|
|
|
|
|
371
|
0
|
0
|
|
|
|
|
$nv = $next->suggestvar($fv.'_via') # Make _via |
|
372
|
|
|
|
|
|
|
unless (defined $nv); |
|
373
|
|
|
|
|
|
|
|
|
374
|
0
|
|
|
|
|
|
$nID = $next->addvar($nv, 'wire', 'via'); |
|
375
|
0
|
|
|
|
|
|
$next->attach($f, $nID); # This will also get the 'dim' property right |
|
376
|
0
|
|
|
|
|
|
$where{$next}=$nv; # Register it, so we won't do this again |
|
377
|
|
|
|
|
|
|
} |
|
378
|
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
# Now we change the variable's type if needed. |
|
380
|
0
|
|
|
|
|
|
$wf = $where{$from}; # We use it a lot here, so... |
|
381
|
0
|
|
|
|
|
|
$tmp = $toout{$from->get(['vars',$wf,'type'])}; |
|
382
|
0
|
0
|
|
|
|
|
blow("Expected a variable convertable to output/inout, got ". |
|
383
|
|
|
|
|
|
|
"variable \'$wf\' of type \'".$from->get(['vars',$wf,'type'])."\' on ". |
|
384
|
|
|
|
|
|
|
$from->who."\n") |
|
385
|
|
|
|
|
|
|
unless (defined $tmp); |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
# We can't change variable types of static objects. Be sure. |
|
388
|
|
|
|
|
|
|
|
|
389
|
0
|
0
|
|
|
|
|
if ($from->get('static')) { |
|
390
|
0
|
0
|
|
|
|
|
wrong("Attempted to change the variable type of $wf to $tmp in ". |
|
391
|
|
|
|
|
|
|
$from->who()." but it is a static Verilog object\n") |
|
392
|
|
|
|
|
|
|
unless ($from->get(['vars',$wf,'type']) eq $tmp) |
|
393
|
|
|
|
|
|
|
} else { |
|
394
|
0
|
|
|
|
|
|
$from->set(['vars',$wf,'type'], $tmp); |
|
395
|
|
|
|
|
|
|
} |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
# And finally, we register the connection in 'inshash'. If the entry |
|
398
|
|
|
|
|
|
|
# is already initialized, then we've already connected that variable. |
|
399
|
|
|
|
|
|
|
# We use an assign instead. Note that this won't work with zouts. |
|
400
|
0
|
|
|
|
|
|
$hashref = $from->get('inshash'); |
|
401
|
0
|
|
|
|
|
|
$tmp = ${$hashref}{$wf}; |
|
|
0
|
|
|
|
|
|
|
|
402
|
0
|
0
|
0
|
|
|
|
if ((defined $tmp) && ($tmp ne $nv)) { |
|
403
|
0
|
|
|
|
|
|
$next->append(" assign $nv = $tmp;\n"); |
|
404
|
|
|
|
|
|
|
} else { |
|
405
|
0
|
|
|
|
|
|
${$hashref}{$wf}=$nv; |
|
|
0
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
} |
|
407
|
|
|
|
|
|
|
} |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
# Now it's time to see if we're finished. That is, have we |
|
410
|
|
|
|
|
|
|
# reached our destination? |
|
411
|
|
|
|
|
|
|
|
|
412
|
0
|
0
|
|
|
|
|
last SLOOP if ($next == $to); |
|
413
|
|
|
|
|
|
|
|
|
414
|
0
|
|
|
|
|
|
$from = $next; # This is the actual walking |
|
415
|
|
|
|
|
|
|
} |
|
416
|
|
|
|
|
|
|
} |
|
417
|
|
|
|
|
|
|
} |
|
418
|
|
|
|
|
|
|
} |
|
419
|
|
|
|
|
|
|
} |