File Coverage

blib/lib/Verilog/Netlist/Pin.pm
Criterion Covered Total %
statement 141 162 87.0
branch 49 76 64.4
condition 20 26 76.9
subroutine 22 26 84.6
pod 11 15 73.3
total 243 305 79.6


line stmt bran cond sub pod time code
1             # Verilog - Verilog Perl Interface
2             # See copyright, etc in below POD section.
3             ######################################################################
4              
5             package Verilog::Netlist::Pin;
6              
7 8     8   57 use Verilog::Netlist;
  8         14  
  8         233  
8 8     8   3269 use Verilog::Netlist::Port;
  8         22  
  8         437  
9 8     8   60 use Verilog::Netlist::Net;
  8         16  
  8         248  
10 8     8   3750 use Verilog::Netlist::Cell;
  8         23  
  8         380  
11 8     8   4144 use Verilog::Netlist::Module;
  8         28  
  8         492  
12 8     8   73 use Verilog::Netlist::Pin;
  8         13  
  8         166  
13 8     8   3934 use Verilog::Netlist::PinSelection;
  8         20  
  8         273  
14 8     8   49 use Verilog::Netlist::Subclass;
  8         13  
  8         378  
15 8     8   45 use vars qw($VERSION @ISA);
  8         15  
  8         312  
16 8     8   39 use strict;
  8         13  
  8         13249  
17             @ISA = qw(Verilog::Netlist::Pin::Struct
18             Verilog::Netlist::Subclass);
19              
20             $VERSION = '3.476';
21              
22             structs('_new_base',
23             'Verilog::Netlist::Pin::Struct'
24             =>[name => '$', #' # Pin connection
25             filename => '$', #' # Filename this came from
26             lineno => '$', #' # Linenumber this came from
27             userdata => '%', # User information
28             attributes => '%', #' # Misc attributes for systemperl or other processors
29             #
30             comment => '$', #' # Comment provided by user
31             _pinselects => '$', #' # Arrayref to Verilog::Netlist::PinSelections
32             portname => '$', #' # Port connection name
33             portnumber => '$', #' # Position of name in call
34             pinnamed => '$', #' # True if name assigned
35             cell => '$', #' # Cell reference
36             # below only after link()
37             _nets => '$', #' # Arrayref to references to connected nets
38             port => '$', #' # Port connection reference
39             # SystemPerl: below only after autos()
40             sp_autocreated => '$', #' # Created by auto()
41             # below by accessor computation
42             #module
43             #submod
44             ]);
45              
46             sub new {
47 851     851 0 1262 my $class = shift;
48 851         3046 my %params = (@_);
49 851 100       1720 if (defined $params{netname}) {
    50          
50             # handle legacy constructor parameter "netname"
51 843         2798 $params{_pinselects} = [new Verilog::Netlist::PinSelection($params{netname})];
52 843         1516 delete $params{netname};
53             } elsif (defined $params{pinselects}) {
54             # remap pinselects to _pinselects
55 8         12 foreach my $pinselect (@{$params{pinselects}}) {
  8         18  
56 9         41 push @{$params{_pinselects}},
57             new Verilog::Netlist::PinSelection($pinselect->{netname},
58             $pinselect->{msb},
59 9         12 $pinselect->{lsb});
60             }
61 8         17 delete $params{pinselects};
62             }
63 851         17083 return $class->_new_base(%params);
64             }
65              
66             sub delete {
67 806     806 1 1005 my $self = shift;
68 806 100 100     1352 if ($self->nets && $self->port) {
69 5         11 foreach my $net ($self->nets) {
70 5 50       15 next unless $net->{net};
71 5         65 my $dir = $self->port->direction;
72 5 50       11 if ($dir eq 'in') {
    0          
    0          
73 5         16 $net->{net}->_used_in_dec();
74             } elsif ($dir eq 'out') {
75 0         0 $net->{net}->_used_out_dec();
76             } elsif ($dir eq 'inout') {
77 0         0 $net->{net}->_used_inout_dec();
78             }
79             }
80             }
81 806         10510 my $h = $self->cell->_pins;
82 806         10105 delete $h->{$self->name};
83 806         1747 return undef;
84             }
85              
86             ######################################################################
87             #### Methods
88              
89             # Legacy accessors
90             sub netname {
91 7 50   7 1 90 return undef if !defined($_[0]->_pinselects);
92 7         9 return @{$_[0]->_pinselects}[0]->{_netname};
  7         90  
93             }
94             sub net {
95 0     0 1 0 my $nets = $_[0]->_nets;
96 0 0       0 return undef if !defined($nets);
97 0 0       0 return undef if !@{$nets}[0];
  0         0  
98 0         0 return @{$nets}[0]->{net};
  0         0  
99             }
100              
101             # Standard accessors
102             sub nets {
103 951 100   951 1 12556 return [] if !defined($_[0]->_nets);
104 151         188 return (@{$_[0]->_nets});
  151         1844  
105             }
106             sub nets_sorted {
107 0 0   0 1 0 return [] if !defined($_[0]->_nets);
108 0         0 return (sort {$a->name cmp $b->name} (@{$_[0]->_nets}));
  0         0  
  0         0  
109             }
110             sub pinselects {
111 154 50   154 1 2048 return [] if !defined($_[0]->_pinselects);
112 154         182 return @{$_[0]->_pinselects};
  154         1917  
113             }
114             sub logger {
115 0     0 1 0 return $_[0]->netlist->logger;
116             }
117             sub module {
118 52     52 1 684 return $_[0]->cell->module;
119             }
120             sub submod {
121 61     61 0 781 return $_[0]->cell->submod;
122             }
123             sub netlist {
124 0     0 1 0 return $_[0]->cell->module->netlist;
125             }
126              
127             sub _link {
128 104     104   134 my $self = shift;
129             # Note this routine is HOT
130 104         118 my $change;
131 104 100       1345 if (!$self->_nets) {
132 51 50       664 if ($self->_pinselects) {
133 51         90 my @nets = ();
134 51         56 foreach my $pinselect (@{$self->_pinselects}) {
  51         636  
135 52         123 my $net = $self->module->find_net($pinselect->netname);
136 52 100       136 next if (!defined($net));
137 22         73 my ($msb, $lsb);
138             # if the parsed description includes a range, use that,
139             # else use the complete range of the underlying net.
140 22 100       63 if (defined($pinselect->msb)) {
141 3         7 $msb = $pinselect->msb;
142 3         9 $lsb = $pinselect->lsb;
143             } else {
144 19         297 $msb = $net->msb;
145 19         266 $lsb = $net->lsb;
146             }
147 22         119 push(@nets, {net => $net, msb => $msb, lsb => $lsb});
148             }
149 51         729 $self->_nets(\@nets);
150 51         85 $change = 1;
151             }
152             }
153 104 100       1339 if (!$self->port) {
154 59 100       146 if (my $submod = $self->submod) {
155 51         683 my $portname = $self->portname;
156 51 100 66     719 if ($portname && !$self->cell->byorder ) {
157 34         97 $self->port($submod->find_port($portname));
158 34         50 $change = 1;
159             }
160             else {
161 17         274 $self->port($submod->find_port_by_index($self->portnumber));
162             # changing name from pin# to actual port name
163 17 50       276 $self->name($self->port->name) if $self->port;
164 17         32 $change = 1;
165             }
166             }
167             }
168 104 100 66     871 if ($change && $self->_nets && $self->port) {
      100        
169 45         559 my $dir = $self->port->direction;
170 45         114 foreach my $net ($self->nets) {
171 18 50       46 next unless $net->{net};
172 18 100       50 if ($dir eq 'in') {
    50          
    0          
173 14         45 $net->{net}->_used_in_inc();
174             } elsif ($dir eq 'out') {
175 4         13 $net->{net}->_used_out_inc();
176             } elsif ($dir eq 'inout') {
177 0         0 $net->{net}->_used_inout_inc();
178             }
179             }
180             }
181             }
182              
183             sub type_match {
184 17     17 0 26 my $self = shift;
185             # We could check for specific types being OK, but nearly everything,
186             # reg/trireg/wire/wand etc/tri/ supply0|1 etc
187             # is allowed to connect with everything else, and we're not a lint tool...
188             # So, not: return $self->net->data_type eq $self->port->data_type;
189 17         47 return 1;
190             }
191              
192             sub lint {
193 40     40 1 49 my $self = shift;
194 40 50 66     577 if (!$self->port && $self->submod) {
195 0         0 $self->error($self,"Port not found in ",$self->submod->keyword," ",$self->submod->name,": ",$self->portname,"\n");
196             }
197 40 100 100     498 if ($self->port && $self->nets) {
198 17 50       41 if (!$self->type_match) {
199 0         0 my $nettype = $self->net->data_type;
200 0         0 my $porttype = $self->port->data_type;
201 0         0 $self->error("Port pin data type '$porttype' != Net data type '$nettype': "
202             ,$self->name,"\n");
203             }
204              
205 17         35 foreach my $net ($self->nets) {
206 17 100 66     251 next unless $net->{net} && $net->{net}->port;
207 6         86 my $portdir = $self->port->direction;
208 6         84 my $netdir = $net->{net}->port->direction;
209 6 50 66     42 if (($netdir eq "in" && $portdir eq "out")
210             #Legal: ($netdir eq "in" && $portdir eq "inout")
211             #Legal: ($netdir eq "out" && $portdir eq "inout")
212             ) {
213 0         0 $self->error("Port is ${portdir}put from submodule, but ${netdir}put from this module: "
214             ,$self->name,"\n");
215             #$self->cell->module->netlist->dump;
216             }
217             }
218             }
219             }
220              
221             sub verilog_text {
222 37     37 0 42 my $self = shift;
223 37         42 my $inst;
224 37 100       488 if ($self->port) { # Even if it was by position, after linking we can write it as if it's by name.
    50          
225 34         414 $inst = ".".$self->port->name."(";
226             } elsif ($self->pinnamed) {
227 3         42 $inst = ".".$self->name."(";
228             } else { # not by name, and unlinked
229 0         0 $inst = ".".$self->portname."(";
230             }
231 37         91 my $net_cnt = $self->pinselects;
232 37 100       93 if ($net_cnt >= 2) {
    50          
233 1         4 $inst .= "{";
234 1         2 my $comma = "";
235 1         3 foreach my $pinselect (reverse($self->pinselects)) {
236 2         4 $inst .= $comma;
237 2         6 $inst .= $pinselect->bracketed_msb_lsb;
238 2         4 $comma = ",";
239             }
240 1         2 $inst .= "}";
241             } elsif ($net_cnt == 1) {
242 36         59 my @tmp = $self->pinselects;
243 36         91 $inst .= $tmp[0]->bracketed_msb_lsb;
244             }
245              
246 37         63 $inst .= ")";
247 37         86 return $inst;
248             }
249              
250             sub dump {
251 40     40 1 53 my $self = shift;
252 40   50     74 my $indent = shift||0;
253 40         88 my $net_cnt = $self->pinselects;
254 40         560 my $out = " "x$indent."Pin:".$self->name;
255 40 100       98 $out .= ($net_cnt > 1) ? " Nets:" : " Net:";
256 40         51 my $comma = "";
257 40         74 foreach my $pinselect (reverse($self->pinselects)) {
258 41         60 $out .= $comma;
259 41         121 $out .= $pinselect->bracketed_msb_lsb;
260 41         74 $comma = ",";
261             }
262 40         547 print "$out\n";
263 40 100       827 if ($self->port) {
264 37         477 $self->port->dump($indent+10, 'norecurse');
265             }
266 40         169 foreach my $net ($self->nets) {
267 18 50       53 next unless $net->{net};
268 18         67 $net->{net}->dump($indent+10, 'norecurse');
269             }
270             }
271              
272             ######################################################################
273             #### Package return
274             1;
275             __END__