Silicon-Chip
view release on metacpan or search on metacpan
lib/Silicon/Chip.pm view on Meta::CPAN
}
}
my @hc = (stroke => "darkgreen", stroke_width => Fw); # Horizontal line color
my @vc = (stroke => "darkgreen", stroke_width => Fw); # Vertical line color
for my $i(keys @f) # Draw horizontal and vertical bars with a minimal number of lines otherwise the svg files get very big
{for my $j(keys $f[$i]->@*)
{if (defined(my $h = $H[$i][$j])) # Horizontal
{my $e = $i;
for my $I($i..$#f) # Go as far right as possible
{my $H = \$H[$I][$j];
last unless $$H and $$H eq $h; # Still in line
$$H = undef; # Erase line as no longer needed
$e = $I; # Current known end of the line
}
$svg->line(x1=>$i, y1=>$j+1/2, x2=>$e+1, y2=>$j+1/2, @hc); # Draw horizontal line
}
if (defined(my $v = $V[$i][$j])) # Vertical
{my $e = $j;
for my $J($j..$f[$i]->$#*) # Go as far down as possible
{my $V = \$V[$i][$J];
last unless $$V and $$V eq $v; # Still in line
$$V = undef; # Erase line as no longer needed
$e = $J; # Current known end of the line
}
$svg->line(x1=>$i+1/2, y1=>$j, x2=>$i+1/2, y2=>$e+1, @vc); # Draw vertical line
}
}
}
}
my $t = $svg->print; # Text of svg
my $f = $options{svg}; # Svg file
return owf(fpe($f, q(svg)), $t) if $f; # Draw bundle as an svg drawing
$t
}
my %drawMask; # Track masks drawn so we can complain about duplicates
my sub drawMask($%) # Draw a mask for the gates.
{my ($chip, %options) = @_; # Chip, options
my $s = $options{svg};
$drawMask{$s}++ and confess <<"END" =~ s/\n(.)/ $1/gsr; # Complain about duplicate mask names
Duplicate mask name: $s specified
END
my $layout = layoutAsFiberBundle($chip, %options); # Gates on chip
$layout->draw(%options); # Draw mask
}
#D1 Basic Circuits # Some well known basic circuits.
sub n(*$) # Gate name from single index.
{my ($c, $i) = @_; # Gate name, bit number
!@_ or !ref($_[0]) or confess <<"END";
Call as a sub not as a method
END
"${c}_$i"
}
sub nn(*$$) # Gate name from double index.
{my ($c, $i, $j) = @_; # Gate name, word number, bit number
!@_ or !ref($_[0]) or confess confess <<"END";
Call as a sub not as a method
END
"${c}_${i}_$j"
}
#D2 Comparisons # Compare unsigned binary integers of specified bit widths.
sub compareEq($$$$%) # Compare two unsigned binary integers of a specified width returning B<1> if they are equal else B<0>.
{my ($chip, $output, $a, $b, %options) = @_; # Chip, name of component also the output bus, first integer, second integer, options
@_ >= 4 or confess "Four or more parameters";
my $o = $output;
my $A = sizeBits($chip, $a);
my $B = sizeBits($chip, $b);
$A == $B or confess <<"END" =~ s/\n(.)/ $1/gsr;
Input $a has width $A but input $b has width $B
END
$chip->nxor(n("$o.e", $_), n($a, $_), n($b, $_)) for 1..$B; # Test each bit pair for equality
$chip->andBits($o, "$o.e", bits=>$B); # All bits must be equal
$chip
}
sub compareGt($$$$%) # Compare two unsigned binary integers and return B<1> if the first integer is more than B<b> else B<0>.
{my ($chip, $output, $a, $b, %options) = @_; # Chip, name of component also the output bus, first integer, second integer, options
@_ >= 4 or confess "Four or more parameters";
my $o = $output;
my $A = sizeBits($chip, $a);
my $B = sizeBits($chip, $b);
$A == $B or confess <<"END" =~ s/\n(.)/ $1/gsr;
Input $a has width $A but input $b has width $B
END
$chip->nxor (n("$o.e", $_), n($a, $_), n($b, $_)) for 2..$B; # Test all but the lowest bit pair for equality
$chip->gt (n("$o.g", $_), n($a, $_), n($b, $_)) for 1..$B; # Test each bit pair for more than
for my $b(2..$B) # More than on one bit and all preceding bits are equal
{$chip->and(n("$o.c", $b),
{(map {$_=>n("$o.e", $_)} $b..$B), ($b-1)=>n("$o.g", $b-1)});
}
$chip->or ($o, {$B=>n("$o.g", $B), (map {($_-1)=>n("$o.c", $_)} 2..$B)}); # Any set bit indicates that B<a> is more than B<b>
$chip
}
sub compareLt($$$$%) # Compare two unsigned binary integers B<a>, B<b> of a specified width. Output B<out> is B<1> if B<a> is less than B<b> else B<0>.
{my ($chip, $output, $a, $b, %options) = @_; # Chip, name of component also the output bus, first integer, second integer, options
@_ >= 4 or confess "Four or more parameters";
my $A = sizeBits($chip, $a);
my $B = sizeBits($chip, $b);
$A == $B or confess <<"END" =~ s/\n(.)/ $1/gsr;
Input $a has width $A but input $b has width $B
END
my $o = $output;
$chip->nxor (n("$o.e", $_), n($a, $_), n($b, $_)) for 2..$B; # Test all but the lowest bit pair for equality
$chip->lt (n("$o.l", $_), n($a, $_), n($b, $_)) for 1..$B; # Test each bit pair for less than
( run in 3.194 seconds using v1.01-cache-2.11-cpan-5c0b1e786e0 )