Name

Silicon::Chip - Design a silicon chip by combining logic gates and sub chips.

Synopsis

Create a chip to compare two 4 bit big endian unsigned integers for equality:

my $B = 4;                                              # Number of bits

my $c = Silicon::Chip::newChip(title=>"$B Bit Equals"); # Create chip

$c->input ("a$_")                       for 1..$B;      # First number
$c->input ("b$_")                       for 1..$B;      # Second number

$c->nxor  ("e$_", {1=>"a$_", 2=>"b$_"}) for 1..$B;      # Test each bit for equality
$c->and   ("and", {map{$_=>"e$_"}           1..$B});    # And tests together to get total equality

$c->output("out", "and");                               # Output gate

my $s = $c->simulate({a1=>1, a2=>0, a3=>1, a4=>0,       # Input gate values
                      b1=>1, b2=>0, b3=>1, b4=>0},
                      svg=>"svg/Equals$B");             # Svg drawing of layout

is_deeply($s->steps,         3);                        # Three steps
is_deeply($s->values->{out}, 1);                        # Out is 1 for equals

my $t = $c->simulate({a1=>1, a2=>1, a3=>1, a4=>0,
                      b1=>1, b2=>0, b3=>1, b4=>0});
is_deeply($t->values->{out}, 0);                        # Out is 0 for not equals

To obtain:

Other circuit diagrams can be seen in folder: lib/Silicon/svg

Description

Design a silicon chip by combining logic gates and sub chips.

Version 20231111.

The following sections describe the methods in each functional area of this module. For an alphabetic listing of all methods by name see Index.

Construct

Construct a Silicon chip using standard logic gates, components and sub chips combined via buses.

newChip (%options)

Create a new chip.

   Parameter  Description
1  %options   Options

Example:

if (1)

 {my $c = Silicon::Chip::newChip;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  $c->one ("one");
  $c->zero("zero");
  $c->or  ("or",   [qw(one zero)]);
  $c->and ("and",  [qw(one zero)]);
  $c->output("o1", "or");
  $c->output("o2", "and");
  my $s = $c->simulate({}, svg=>q(svg/oneZero));
  is_deeply($s->steps       , 3);
  is_deeply($s->value("o1"), 1);
  is_deeply($s->value("o2"), 0);
 }
if (1)                                                                           # Single AND gate

 {my $c = Silicon::Chip::newChip;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  $c->input ("i1");
  $c->input ("i2");
  $c->and   ("and1", [qw(i1 i2)]);
  $c->output("o", "and1");
  my $s = $c->simulate({i1=>1, i2=>1});
  ok($s->steps         == 2);
  ok($s->value("and1") == 1);
 }

if (1)                                                                          # 4 bit equal
 {my $B = 4;                                                                    # Number of bits


  my $c = Silicon::Chip::newChip(title=><<"END");                               # Create chip  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

$B Bit Equals
END
  $c->input ("a$_")                 for 1..$B;                                  # First number
  $c->input ("b$_")                 for 1..$B;                                  # Second number

  $c->nxor  ("e$_", "a$_", "b$_")   for 1..$B;                                  # Test each bit for equality
  $c->and   ("and", {map{$_=>"e$_"}     1..$B});                                # And tests together to get total equality

  $c->output("out", "and");                                                     # Output gate

  my $s = $c->simulate({a1=>1, a2=>0, a3=>1, a4=>0,                             # Input gate values
                        b1=>1, b2=>0, b3=>1, b4=>0},
                        svg=>q(svg/Equals));                                    # Svg drawing of layout

  is_deeply($s->steps,        3);                                               # Three steps
  is_deeply($s->value("out"), 1);                                               # Out is 1 for equals

  my $t = $c->simulate({a1=>1, a2=>1, a3=>1, a4=>0,
                        b1=>1, b2=>0, b3=>1, b4=>0});
  is_deeply($t->value("out"), 0);                                               # Out is 0 for not equals
 }

gate($chip, $type, $output, $input1, $input2)

A logic gate chosen from and|continue|gt|input|lt|nand|nor|not|nxor|one|or|output|xor|zero. The gate type can be used as a method name, so ->gate("and", can be reduced to ->and(.

   Parameter  Description
1  $chip      Chip
2  $type      Gate type
3  $output    Output name
4  $input1    Input from another gate
5  $input2    Input from another gate

Example:

if (1)                                                                           # Two AND gates driving an OR gate  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

 {my $c = newChip;
  $c->input ("i11");
  $c->input ("i12");
  $c->and   ("and1", [qw(i11   i12)]);
  $c->input ("i21");
  $c->input ("i22");
  $c->and   ("and2", [qw(i21   i22 )]);
  $c->or    ("or",   [qw(and1  and2)]);
  $c->output( "o", "or");
  my $s = $c->simulate({i11=>1, i12=>1, i21=>1, i22=>1});
  ok($s->steps        == 3);
  ok($s->value("or")  == 1);
     $s  = $c->simulate({i11=>1, i12=>0, i21=>1, i22=>1});
  ok($s->steps        == 3);
  ok($s->value("or")  == 1);
     $s  = $c->simulate({i11=>1, i12=>0, i21=>1, i22=>0});
  ok($s->steps        == 3);
  ok($s->value("o")   == 0);
 }

connectInput($chip, $in, $to, %options)

Connect a previously defined input gate to the output of another previously gate on the same chip. This allows us to define a set of gates on the chip without having to know, first, all the names of the gates that will provide input to these gates.

   Parameter  Description
1  $chip      Chip
2  $in        Input gate
3  $to        Gate to connect input gate to
4  %options   Options

Example:

if (1)                                                                          # Internal input gate
 {my $c = newChip();
     $c->input ('i');                                                           # Input
     $c->input ('j');                                                           # Internal input which we will connect to later
     $c->output(qw(o j));                                                       # Output


     $c->connectInput(qw(j i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


  my $s = $c->simulate({i=>1});
  is_deeply($s->steps, 1);
  is_deeply($s->value("j"), undef);
  is_deeply($s->value("o"), 1);
 }

if (1)                                                                           # Internal input gate
 {my @n = qw(3 2 1 2 3);
  my $c = newChip();
     $c->words('i', 2, @n);                                                     # Input
     $c->outputWords(qw(o i));                                                  # Output
  my $s = $c->simulate({});
  is_deeply($s->steps, 2);
  is_deeply([$s->wordsToInteger("i")], [@n]);
 }

if (1)                                                                           # Internal input gate
 {my @n = qw(3 2 1 2 3);
  my $c = newChip();
     $c->words('i', 2, @n);                                                     # Input
     $c->outputWords(qw(o i));                                                  # Output
  my $s = $c->simulate({});
  is_deeply($s->steps, 2);
  is_deeply([$s->wordsToInteger("i")], [@n]);
 }

Buses

A bus is an array of bits or an array of arrays of bits

Bits

An array of bits that can be manipulated via one name.

setSizeBits ($chip, $name, $bits, %options)

Set the size of a bits bus.

   Parameter  Description
1  $chip      Chip
2  $name      Bits bus name
3  $bits      Options
4  %options

Example:

if (1)
 {my $c = newChip();

  $c->setSizeBits ('i', 2);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  $c->setSizeWords('j', 3, 2);
  is_deeply($c->sizeBits,  {i => 2, j_1 => 2, j_2 => 2, j_3 => 2});
  is_deeply($c->sizeWords, {j => [3, 2]});
 }

bits($chip, $name, $bits, $value, %options)

Create a bus set to a specified number.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $bits      Width in bits of bus
4  $value     Value of bus
5  %options   Options

Example:

if (1)
 {my $N = 4;
  for my $i(0..2**$N-1)
   {my $c = Silicon::Chip::newChip;

    $c->bits      ("c", $N, $i);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $c->outputBits("o", "c");

    my $s = $c->simulate({}, $i == 3 ? (svg=>q(svg/bits)) : ());  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    is_deeply($s->steps, 2);
    is_deeply($s->bint("o"), $i);
   }
 }

inputBits ($chip, $name, $bits, %options)

Create an input bus made of bits.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $bits      Width in bits of bus
4  %options   Options

Example:

if (1)
 {my $W = 8;
  my $i = newChip(name=>"not");

     $i->inputBits('i',      $W);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $i->notBits  (qw(n i));
     $i->outputBits(qw(o n));

  my $o = newChip(name=>"outer");

     $o->inputBits ('a',     $W);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $o->outputBits(qw(A a));

     $o->inputBits ('b',     $W);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $o->outputBits(qw(B b));

  my %i = connectBits($i, 'i', $o, 'A');
  my %o = connectBits($i, 'o', $o, 'b');
  $o->install($i, {%i}, {%o});

  my %d = setBits($o, 'a', 0b10110);
  my $s = $o->simulate({%d}, svg=>q(svg/not));
  is_deeply($s->bint('B'), 0b11101001);
 }

outputBits ($chip, $name, $input, %options)

Create an output bus made of bits.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Name of inputs
4  %options   Options

Example:

if (1)
 {my $W = 8;
  my $i = newChip(name=>"not");
     $i->inputBits('i',      $W);
     $i->notBits  (qw(n i));

     $i->outputBits(qw(o n));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


  my $o = newChip(name=>"outer");
     $o->inputBits ('a',     $W);

     $o->outputBits(qw(A a));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $o->inputBits ('b',     $W);

     $o->outputBits(qw(B b));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


  my %i = connectBits($i, 'i', $o, 'A');
  my %o = connectBits($i, 'o', $o, 'b');
  $o->install($i, {%i}, {%o});

  my %d = setBits($o, 'a', 0b10110);
  my $s = $o->simulate({%d}, svg=>q(svg/not));
  is_deeply($s->bint('B'), 0b11101001);
 }
if (1)
 {my @B = ((my $W = 4), (my $B = 2));

  my $c = newChip();
     $c->inputWords ('i', @B);
     $c->andWords   (qw(and  i));
     $c->andWordsX  (qw(andX i));
     $c-> orWords   (qw( or  i));
     $c-> orWordsX  (qw( orX i));
     $c->notWords   (qw(n    i));

     $c->outputBits (qw(And  and));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


     $c->outputBits (qw(AndX andX));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


     $c->outputBits (qw(Or   or));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


     $c->outputBits (qw(OrX  orX));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputWords(qw(N    n));
  my %d = setWords($c, 'i', 0b00, 0b01, 0b10, 0b11);
  my $s = $c->simulate({%d}, svg=>"svg/andOrWords$W");

  is_deeply($s->bint('And'),  0b1000);
  is_deeply($s->bint('AndX'), 0b0000);

  is_deeply($s->bint('Or'),  0b1110);
  is_deeply($s->bint('OrX'), 0b11);
  is_deeply([$s->wordsToInteger('N')], [3, 2, 1, 0]);
 }

notBits ($chip, $name, $input, %options)

Create a not bus made of bits.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Name of inputs
4  %options   Options

Example:

if (1)
 {my $W = 8;
  my $i = newChip(name=>"not");
     $i->inputBits('i',      $W);

     $i->notBits  (qw(n i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $i->outputBits(qw(o n));

  my $o = newChip(name=>"outer");
     $o->inputBits ('a',     $W);
     $o->outputBits(qw(A a));
     $o->inputBits ('b',     $W);
     $o->outputBits(qw(B b));

  my %i = connectBits($i, 'i', $o, 'A');
  my %o = connectBits($i, 'o', $o, 'b');
  $o->install($i, {%i}, {%o});

  my %d = setBits($o, 'a', 0b10110);
  my $s = $o->simulate({%d}, svg=>q(svg/not));
  is_deeply($s->bint('B'), 0b11101001);
 }

andBits ($chip, $name, $input, %options)

and a bus made of bits.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Name of inputs
4  %options   Options

Example:

if (1)
 {my $W = 8;

  my $c = newChip();
     $c-> inputBits('i',         $W);

     $c->   andBits(qw(and  i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->    orBits(qw(or   i));
     $c->  nandBits(qw(nand i));
     $c->   norBits(qw(nor  i));
     $c->output    (qw(And  and));
     $c->output    (qw(Or   or));
     $c->output    (qw(nAnd nand));
     $c->output    (qw(nOr  nor));

  my %d = setBits($c, 'i', 0b10110);
  my $s = $c->simulate({%d}, svg=>q(svg/andOrBits));

  is_deeply($s->value("And"),  0);
  is_deeply($s->value("Or"),   1);
  is_deeply($s->value("nAnd"), 1);
  is_deeply($s->value("nOr"),  0);
 }

nandBits($chip, $name, $input, %options)

nand a bus made of bits.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Name of inputs
4  %options   Options

Example:

if (1)
 {my $W = 8;

  my $c = newChip();
     $c-> inputBits('i',         $W);
     $c->   andBits(qw(and  i));
     $c->    orBits(qw(or   i));

     $c->  nandBits(qw(nand i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->   norBits(qw(nor  i));
     $c->output    (qw(And  and));
     $c->output    (qw(Or   or));
     $c->output    (qw(nAnd nand));
     $c->output    (qw(nOr  nor));

  my %d = setBits($c, 'i', 0b10110);
  my $s = $c->simulate({%d}, svg=>q(svg/andOrBits));

  is_deeply($s->value("And"),  0);
  is_deeply($s->value("Or"),   1);
  is_deeply($s->value("nAnd"), 1);
  is_deeply($s->value("nOr"),  0);
 }

orBits ($chip, $name, $input, %options)

or a bus made of bits.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Options
4  %options

Example:

if (1)
 {my $W = 8;

  my $c = newChip();
     $c-> inputBits('i',         $W);
     $c->   andBits(qw(and  i));

     $c->    orBits(qw(or   i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->  nandBits(qw(nand i));
     $c->   norBits(qw(nor  i));
     $c->output    (qw(And  and));
     $c->output    (qw(Or   or));
     $c->output    (qw(nAnd nand));
     $c->output    (qw(nOr  nor));

  my %d = setBits($c, 'i', 0b10110);
  my $s = $c->simulate({%d}, svg=>q(svg/andOrBits));

  is_deeply($s->value("And"),  0);
  is_deeply($s->value("Or"),   1);
  is_deeply($s->value("nAnd"), 1);
  is_deeply($s->value("nOr"),  0);
 }

norBits ($chip, $name, $input, %options)

nor a bus made of bits.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Options
4  %options

Example:

if (1)
 {my $W = 8;

  my $c = newChip();
     $c-> inputBits('i',         $W);
     $c->   andBits(qw(and  i));
     $c->    orBits(qw(or   i));
     $c->  nandBits(qw(nand i));

     $c->   norBits(qw(nor  i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->output    (qw(And  and));
     $c->output    (qw(Or   or));
     $c->output    (qw(nAnd nand));
     $c->output    (qw(nOr  nor));

  my %d = setBits($c, 'i', 0b10110);
  my $s = $c->simulate({%d}, svg=>q(svg/andOrBits));

  is_deeply($s->value("And"),  0);
  is_deeply($s->value("Or"),   1);
  is_deeply($s->value("nAnd"), 1);
  is_deeply($s->value("nOr"),  0);
 }

Words

An array of arrays of bits that can be manipulated via one name.

setSizeWords($chip, $name, $words, $bits, %options)

Set the size of a bits bus.

   Parameter  Description
1  $chip      Chip
2  $name      Bits bus name
3  $words     Words
4  $bits      Bits per word
5  %options   Options

Example:

if (1)
 {my $c = newChip();
  $c->setSizeBits ('i', 2);

  $c->setSizeWords('j', 3, 2);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  is_deeply($c->sizeBits,  {i => 2, j_1 => 2, j_2 => 2, j_3 => 2});
  is_deeply($c->sizeWords, {j => [3, 2]});
 }

words ($chip, $name, $bits, @values)

Create a word bus set to specified numbers.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $bits      Width in bits of each word
4  @values    Values of words

Example:

if (1)                                                                           # Internal input gate
 {my @n = qw(3 2 1 2 3);
  my $c = newChip();

     $c->words('i', 2, @n);                                                     # Input  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputWords(qw(o i));                                                  # Output
  my $s = $c->simulate({});
  is_deeply($s->steps, 2);
  is_deeply([$s->wordsToInteger("i")], [@n]);
 }

if (1)                                                                           # Internal input gate
 {my @n = qw(3 2 1 2 3);
  my $c = newChip();

     $c->words('i', 2, @n);                                                     # Input  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputWords(qw(o i));                                                  # Output
  my $s = $c->simulate({});
  is_deeply($s->steps, 2);
  is_deeply([$s->wordsToInteger("i")], [@n]);
 }

inputWords ($chip, $name, $words, $bits, %options)

Create an input bus made of words.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $words     Width in words of bus
4  $bits      Width in bits of each word on bus
5  %options   Options

Example:

if (1)
 {my @b = ((my $W = 4), (my $B = 3));

  my $c = newChip();

     $c->inputWords ('i',      @b);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputWords(qw(o i));

  my %d = setWords($c, 'i', 0b000, 0b001, 0b010, 0b011);
  my $s = $c->simulate({%d}, svg=>"svg/words$W");

  is_deeply([$s->wordsToInteger('o')], [0..3]);
  is_deeply([$s->wordXToInteger('o')], [10, 12, 0]);
 }

outputWords ($chip, $name, $input, %options)

Create an output bus made of words.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Name of inputs
4  %options   Options

Example:

if (1)
 {my @b = ((my $W = 4), (my $B = 3));

  my $c = newChip();
     $c->inputWords ('i',      @b);

     $c->outputWords(qw(o i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


  my %d = setWords($c, 'i', 0b000, 0b001, 0b010, 0b011);
  my $s = $c->simulate({%d}, svg=>"svg/words$W");

  is_deeply([$s->wordsToInteger('o')], [0..3]);
  is_deeply([$s->wordXToInteger('o')], [10, 12, 0]);
 }

notWords($chip, $name, $input, %options)

Create a not bus made of words.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Name of inputs
4  %options   Options

Example:

if (1)
 {my @B = ((my $W = 4), (my $B = 2));

  my $c = newChip();
     $c->inputWords ('i', @B);
     $c->andWords   (qw(and  i));
     $c->andWordsX  (qw(andX i));
     $c-> orWords   (qw( or  i));
     $c-> orWordsX  (qw( orX i));

     $c->notWords   (qw(n    i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputBits (qw(And  and));
     $c->outputBits (qw(AndX andX));
     $c->outputBits (qw(Or   or));
     $c->outputBits (qw(OrX  orX));
     $c->outputWords(qw(N    n));
  my %d = setWords($c, 'i', 0b00, 0b01, 0b10, 0b11);
  my $s = $c->simulate({%d}, svg=>"svg/andOrWords$W");

  is_deeply($s->bint('And'),  0b1000);
  is_deeply($s->bint('AndX'), 0b0000);

  is_deeply($s->bint('Or'),  0b1110);
  is_deeply($s->bint('OrX'), 0b11);
  is_deeply([$s->wordsToInteger('N')], [3, 2, 1, 0]);
 }

andWords($chip, $name, $input, %options)

and a bus made of words to produce a single word.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Name of inputs
4  %options   Options

Example:

if (1)
 {my @B = ((my $W = 4), (my $B = 2));

  my $c = newChip();
     $c->inputWords ('i', @B);

     $c->andWords   (qw(and  i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->andWordsX  (qw(andX i));
     $c-> orWords   (qw( or  i));
     $c-> orWordsX  (qw( orX i));
     $c->notWords   (qw(n    i));
     $c->outputBits (qw(And  and));
     $c->outputBits (qw(AndX andX));
     $c->outputBits (qw(Or   or));
     $c->outputBits (qw(OrX  orX));
     $c->outputWords(qw(N    n));
  my %d = setWords($c, 'i', 0b00, 0b01, 0b10, 0b11);
  my $s = $c->simulate({%d}, svg=>"svg/andOrWords$W");

  is_deeply($s->bint('And'),  0b1000);
  is_deeply($s->bint('AndX'), 0b0000);

  is_deeply($s->bint('Or'),  0b1110);
  is_deeply($s->bint('OrX'), 0b11);
  is_deeply([$s->wordsToInteger('N')], [3, 2, 1, 0]);
 }

if (1)
 {my @b = ((my $W = 4), (my $B = 3));

  my $c = newChip();
     $c->inputWords ('i',      @b);
     $c->outputWords(qw(o i));

  my %d = setWords($c, 'i', 0b000, 0b001, 0b010, 0b011);
  my $s = $c->simulate({%d}, svg=>"svg/words$W");

  is_deeply([$s->wordsToInteger('o')], [0..3]);
  is_deeply([$s->wordXToInteger('o')], [10, 12, 0]);
 }

andWordsX ($chip, $name, $input, %options)

and a bus made of words by and-ing the corresponding bits in each word to make a single word.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Name of inputs
4  %options   Options

Example:

if (1)
 {my @B = ((my $W = 4), (my $B = 2));

  my $c = newChip();
     $c->inputWords ('i', @B);
     $c->andWords   (qw(and  i));

     $c->andWordsX  (qw(andX i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c-> orWords   (qw( or  i));
     $c-> orWordsX  (qw( orX i));
     $c->notWords   (qw(n    i));
     $c->outputBits (qw(And  and));
     $c->outputBits (qw(AndX andX));
     $c->outputBits (qw(Or   or));
     $c->outputBits (qw(OrX  orX));
     $c->outputWords(qw(N    n));
  my %d = setWords($c, 'i', 0b00, 0b01, 0b10, 0b11);
  my $s = $c->simulate({%d}, svg=>"svg/andOrWords$W");

  is_deeply($s->bint('And'),  0b1000);
  is_deeply($s->bint('AndX'), 0b0000);

  is_deeply($s->bint('Or'),  0b1110);
  is_deeply($s->bint('OrX'), 0b11);
  is_deeply([$s->wordsToInteger('N')], [3, 2, 1, 0]);
 }

orWords ($chip, $name, $input, %options)

or a bus made of words to produce a single word.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Name of inputs
4  %options   Options

Example:

if (1)
 {my @B = ((my $W = 4), (my $B = 2));

  my $c = newChip();
     $c->inputWords ('i', @B);
     $c->andWords   (qw(and  i));
     $c->andWordsX  (qw(andX i));

     $c-> orWords   (qw( or  i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c-> orWordsX  (qw( orX i));
     $c->notWords   (qw(n    i));
     $c->outputBits (qw(And  and));
     $c->outputBits (qw(AndX andX));
     $c->outputBits (qw(Or   or));
     $c->outputBits (qw(OrX  orX));
     $c->outputWords(qw(N    n));
  my %d = setWords($c, 'i', 0b00, 0b01, 0b10, 0b11);
  my $s = $c->simulate({%d}, svg=>"svg/andOrWords$W");

  is_deeply($s->bint('And'),  0b1000);
  is_deeply($s->bint('AndX'), 0b0000);

  is_deeply($s->bint('Or'),  0b1110);
  is_deeply($s->bint('OrX'), 0b11);
  is_deeply([$s->wordsToInteger('N')], [3, 2, 1, 0]);
 }

if (1)
 {my @b = ((my $W = 4), (my $B = 3));

  my $c = newChip();
     $c->inputWords ('i',      @b);
     $c->outputWords(qw(o i));

  my %d = setWords($c, 'i', 0b000, 0b001, 0b010, 0b011);
  my $s = $c->simulate({%d}, svg=>"svg/words$W");

  is_deeply([$s->wordsToInteger('o')], [0..3]);
  is_deeply([$s->wordXToInteger('o')], [10, 12, 0]);
 }

orWordsX($chip, $name, $input, %options)

or a bus made of words by or-ing the corresponding bits in each word to make a single word.

   Parameter  Description
1  $chip      Chip
2  $name      Name of bus
3  $input     Name of inputs
4  %options   Options

Example:

if (1)
 {my @B = ((my $W = 4), (my $B = 2));

  my $c = newChip();
     $c->inputWords ('i', @B);
     $c->andWords   (qw(and  i));
     $c->andWordsX  (qw(andX i));
     $c-> orWords   (qw( or  i));

     $c-> orWordsX  (qw( orX i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->notWords   (qw(n    i));
     $c->outputBits (qw(And  and));
     $c->outputBits (qw(AndX andX));
     $c->outputBits (qw(Or   or));
     $c->outputBits (qw(OrX  orX));
     $c->outputWords(qw(N    n));
  my %d = setWords($c, 'i', 0b00, 0b01, 0b10, 0b11);
  my $s = $c->simulate({%d}, svg=>"svg/andOrWords$W");

  is_deeply($s->bint('And'),  0b1000);
  is_deeply($s->bint('AndX'), 0b0000);

  is_deeply($s->bint('Or'),  0b1110);
  is_deeply($s->bint('OrX'), 0b11);
  is_deeply([$s->wordsToInteger('N')], [3, 2, 1, 0]);
 }

Install

Install a chip within a chip as a sub chip.

install ($chip, $subChip, $inputs, $outputs, %options)

Install a chip within another chip specifying the connections between the inner and outer chip. The same chip can be installed multiple times as each chip description is read only.

   Parameter  Description
1  $chip      Outer chip
2  $subChip   Inner chip
3  $inputs    Inputs of inner chip to to outputs of outer chip
4  $outputs   Outputs of inner chip to inputs of outer chip
5  %options   Options

Example:

if (1)                                                                            # Install one chip inside another chip, specifically one chip that performs NOT is installed once to flip a value
 {my $i = newChip(name=>"not");
     $i-> inputBits('i',     1);
     $i->   notBits(qw(n i));
     $i->outputBits(qw(o n));

  my $o = newChip(name=>"outer");
     $o->inputBits('i', 1); $o->outputBits(qw(n i));
     $o->inputBits('I', 1); $o->outputBits(qw(N I));

  my %i = connectBits($i, 'i', $o, 'n');
  my %o = connectBits($i, 'o', $o, 'I');

  $o->install($i, {%i}, {%o});  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  my %d = $o->setBits('i', 1);
  my $s = $o->simulate({%d}, printOff=>"dump/not1", svg=>"svg/not1");

  is_deeply($s->steps,  2);
  is_deeply($s->values, {"(not 1 n_1)"=>0, "i_1"=>1, "N_1"=>0 });
 }

Visualize

Visualize the chip in various ways.

Dump the logic gates present on a chip.

   Parameter  Description
1  $chip      Chip
2  %options   Gates

Example:

if (1)
 {my $c = Silicon::Chip::newChip(title=>"And gate");
  $c->input ("i1");
  $c->input ("i2");
  $c->and   ("and1", [qw(i1 i2)]);
  $c->output("o", "and1");
  my $s = $c->simulate({i1=>1, i2=>1});


  is_deeply($c->print, <<END);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

i1                              :     input                           i1
i2                              :     input                           i2
and1                            :     and                             i1 i2
o                               :     output                          and1
END


  is_deeply($s->print, <<END);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

i1                              :   1 input                           i1
i2                              :   1 input                           i2
and1                            :   1 and                             i1 i2
o                               :   1 output                          and1
END

  ok($s->printSvg ne $c->printSvg);
 }

Silicon::Chip::Simulation::print($sim, %options)

Print simulation results as text.

   Parameter  Description
1  $sim       Simulation
2  %options   Options

Example:

if (1)
 {my $c = Silicon::Chip::newChip(title=>"And gate");
  $c->input ("i1");
  $c->input ("i2");
  $c->and   ("and1", [qw(i1 i2)]);
  $c->output("o", "and1");
  my $s = $c->simulate({i1=>1, i2=>1});

  is_deeply($c->print, <<END);
i1                              :     input                           i1
i2                              :     input                           i2
and1                            :     and                             i1 i2
o                               :     output                          and1
END

  is_deeply($s->print, <<END);
i1                              :   1 input                           i1
i2                              :   1 input                           i2
and1                            :   1 and                             i1 i2
o                               :   1 output                          and1
END

  ok($s->printSvg ne $c->printSvg);
 }

printSvg($chip, %options)

Dump the logic gates on a chip as an Scalar Vector Graphics drawing to help visualize the structure of the chip.

   Parameter  Description
1  $chip      Chip
2  %options   Options

Example:

if (1)
 {my $c = Silicon::Chip::newChip(title=>"And gate");
  $c->input ("i1");
  $c->input ("i2");
  $c->and   ("and1", [qw(i1 i2)]);
  $c->output("o", "and1");
  my $s = $c->simulate({i1=>1, i2=>1});

  is_deeply($c->print, <<END);
i1                              :     input                           i1
i2                              :     input                           i2
and1                            :     and                             i1 i2
o                               :     output                          and1
END

  is_deeply($s->print, <<END);
i1                              :   1 input                           i1
i2                              :   1 input                           i2
and1                            :   1 and                             i1 i2
o                               :   1 output                          and1
END


  ok($s->printSvg ne $c->printSvg);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

 }

Silicon::Chip::Simulation::printSvg ($sim, %options)

Print simulation results as svg.

   Parameter  Description
1  $sim       Simulation
2  %options   Options

Example:

if (1)
 {my $c = Silicon::Chip::newChip(title=>"And gate");
  $c->input ("i1");
  $c->input ("i2");
  $c->and   ("and1", [qw(i1 i2)]);
  $c->output("o", "and1");
  my $s = $c->simulate({i1=>1, i2=>1});

  is_deeply($c->print, <<END);
i1                              :     input                           i1
i2                              :     input                           i2
and1                            :     and                             i1 i2
o                               :     output                          and1
END

  is_deeply($s->print, <<END);
i1                              :   1 input                           i1
i2                              :   1 input                           i2
and1                            :   1 and                             i1 i2
o                               :   1 output                          and1
END

  ok($s->printSvg ne $c->printSvg);
 }

Basic Circuits

Some well known basic circuits.

n ($c, $i)

Gate name from single index.

   Parameter  Description
1  $c         Gate name
2  $i         Bit number

Example:

if (1)

 {is_deeply( n(a,1),   "a_1");  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  is_deeply(nn(a,1,2), "a_1_2");
 }

nn ($c, $i, $j)

Gate name from double index.

   Parameter  Description
1  $c         Gate name
2  $i         Word number
3  $j         Bit number

Example:

if (1)
 {is_deeply( n(a,1),   "a_1");

  is_deeply(nn(a,1,2), "a_1_2");  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

 }

Comparisons

Compare unsigned binary integers of specified bit widths.

compareEq ($chip, $output, $a, $b, %options)

Compare two unsigned binary integers of a specified width returning 1 if they are equal else 0.

   Parameter  Description
1  $chip      Chip
2  $output    Name of component also the output bus
3  $a         First integer
4  $b         Second integer
5  %options   Options

Example:

if (1)                                                                           # Compare unsigned integers
 {my $B = 2;

  my $c = Silicon::Chip::newChip(title=><<"END");
$B Bit Compare Equal
END
  $c->inputBits($_, $B) for qw(a b);                                            # First and second numbers

  $c->compareEq(qw(o a b));                                                     # Compare equals  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  $c->output   (qw(out o));                                                     # Comparison result

  for   my $i(0..2**$B-1)                                                       # Each possible number
   {for my $j(0..2**$B-1)                                                       # Each possible number
     {my %a = $c->setBits('a', $i);                                             # Number a
      my %b = $c->setBits('b', $j);                                             # Number b

      my $s = $c->simulate({%a, %b}, $i==1&&$j==1?(svg=>"svg/CompareEq$B"):()); # Svg drawing of layout

      is_deeply($s->value("out"), $i == $j ? 1 : 0);                            # Equal
      is_deeply($s->steps, 3);                                                  # Number of steps to stability
     }
   }
 }

compareGt ($chip, $output, $a, $b, %options)

Compare two unsigned binary integers and return 1 if the first integer is more than b else 0.

   Parameter  Description
1  $chip      Chip
2  $output    Name of component also the output bus
3  $a         First integer
4  $b         Second integer
5  %options   Options

Example:

if (1)                                                                           # Compare 8 bit unsigned integers 'a' > 'b' - the pins used to input 'a' must be alphabetically less than those used for 'b'
 {my $B = 3;
  my $c = Silicon::Chip::newChip(title=><<END);
$B Bit Compare more than
END
  $c->inputBits($_, $B) for qw(a b);                                            # First and second numbers

  $c->compareGt(qw(o a b));                                                     # Compare more than  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  $c->output   (qw(out o));                                                     # Comparison result

  for   my $i(0..2**$B-1)                                                       # Each possible number
   {for my $j(0..2**$B-1)                                                       # Each possible number
     {my %a = $c->setBits('a', $i);                                             # Number a
      my %b = $c->setBits('b', $j);                                             # Number b

      my $s = $c->simulate({%a, %b}, $i==2&&$j==1?(svg=>"svg/CompareGt$B"):()); # Svg drawing of layout
      is_deeply($s->value("out"), $i > $j ? 1 : 0);                             # More than
      is_deeply($s->steps, 4);                                                  # Number of steps to stability
     }
   }
 }

compareLt ($chip, $output, $a, $b, %options)

Compare two unsigned binary integers a, b of a specified width. Output out is 1 if a is less than b else 0.

   Parameter  Description
1  $chip      Chip
2  $output    Name of component also the output bus
3  $a         First integer
4  $b         Second integer
5  %options   Options

Example:

if (1)                                                                           # Compare 8 bit unsigned integers 'a' < 'b' - the pins used to input 'a' must be alphabetically less than those used for 'b'
 {my $B = 3;
  my $c = Silicon::Chip::newChip(title=><<"END");
$B Bit Compare Less Than
END
  $c->inputBits($_, $B) for qw(a b);                                            # First and second numbers

  $c->compareLt(qw(o a b));                                                     # Compare less than  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  $c->output   (qw(out o));                                                     # Comparison result

  for   my $i(0..2**$B-1)                                                       # Each possible number
   {for my $j(0..2**$B-1)                                                       # Each possible number
     {my %a = $c->setBits('a', $i);                                             # Number a
      my %b = $c->setBits('b', $j);                                             # Number b

      my $s = $c->simulate({%a, %b}, $i==1&&$j==2?(svg=>"svg/CompareLt$B"):()); # Svg drawing of layout
      is_deeply($s->value("out"), $i < $j ? 1 : 0);                             # More than
      is_deeply($s->steps, 4);                                                  # Number of steps to stability
     }
   }
 }

chooseFromTwoWords ($chip, $output, $a, $b, $choose, %options)

Choose one of two words based on a bit. The first word is chosen if the bit is 0 otherwise the second word is chosen.

   Parameter  Description
1  $chip      Chip
2  $output    Name of component also the chosen word
3  $a         The first word
4  $b         The second word
5  $choose    The choosing bit
6  %options   Options

Example:

if (1)
 {my $B = 4;

  my $c = newChip();
     $c->inputBits('a', $B);                                                    # First word
     $c->inputBits('b', $B);                                                    # Second word
     $c->input    ('c');                                                        # Chooser

     $c->chooseFromTwoWords(qw(o a b c));                                       # Generate gates  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputBits('out', 'o');                                                # Result

  my %a = setBits($c, 'a', 0b0011);
  my %b = setBits($c, 'b', 0b1100);


  my $s = $c->simulate({%a, %b, c=>1}, svg=>q(svg/chooseFromTwoWords));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  is_deeply($s->steps,               4);
  is_deeply($s->bint('out'), 0b1100);

  my $t = $c->simulate({%a, %b, c=>0});
  is_deeply($t->steps,               4);
  is_deeply($t->bint('out'), 0b0011);
 }

enableWord ($chip, $output, $a, $enable, %options)

Output a word or zeros depending on a choice bit. The first word is chosen if the choice bit is 1 otherwise all zeroes are chosen.

   Parameter  Description
1  $chip      Chip
2  $output    Name of component also the chosen word
3  $a         The first word
4  $enable    The second word
5  %options   The choosing bit

Example:

if (1)
 {my $B = 4;

  my $c = newChip();
     $c->inputBits ('a', $B);                                                   # Word
     $c->input     ('c');                                                       # Choice bit

     $c->enableWord(qw(o a c));                                                 # Generate gates  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputBits(qw(out o));                                                 # Result

  my %a = setBits($c, 'a', 3);


  my $s = $c->simulate({%a, c=>1}, svg=>q(svg/enableWord));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  is_deeply($s->steps,               4);
  is_deeply($s->bint('out'), 3);

  my $t = $c->simulate({%a, c=>0});
  is_deeply($t->steps,               4);
  is_deeply($t->bint('out'), 0);
 }

Masks

Point masks and monotone masks. A point mask has a single 1 in a sea of 0s as in 00100. A monotone mask has zero or more 0s followed by all 1s as in: 00111.

pointMaskToInteger ($chip, $output, $input, %options)

Convert a mask i known to have at most a single bit on - also known as a point mask - to an output number a representing the location in the mask of the bit set to 1. If no such bit exists in the point mask then output number a is 0.

   Parameter  Description
1  $chip      Chip
2  $output    Output name
3  $input     Input mask
4  %options   Options

Example:

if (1)
 {my $B = 4;
  my $N = 2**$B-1;

  my $c = Silicon::Chip::newChip(title=><<"END");
$B bits point mask to integer
END
  $c->inputBits         (qw(    i), $N);                                        # Mask with no more than one bit on

  $c->pointMaskToInteger(qw(o   i));                                            # Convert  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  $c->outputBits        (qw(out o));                                            # Mask with no more than one bit on

  for my $i(0..$N)                                                              # Each position of mask
   {my %i = setBits($c, 'i', $i ? 1<<($i-1) : 0);                               # Point in each position with zero representing no position
    my $s = $c->simulate(\%i, $i == 5 ? (svg=>"svg/point$B") : ());
    is_deeply($s->steps, 2);
    my %o = $s->values->%*;                                                     # Output bits
    my $n = eval join '', '0b', map {$o{n(o,$_)}} reverse 1..$B;                # Output bits as number
    is_deeply($n, $i);
   }
 }

integerToPointMask ($chip, $output, $input, %options)

Convert an integer i of specified width to a point mask m. If the input integer is 0 then the mask is all zeroes as well.

   Parameter  Description
1  $chip      Chip
2  $output    Output name
3  $input     Input mask
4  %options   Options

Example:

if (1)
 {my $B = 3;
  my $N = 2**$B-1;

  my $c = Silicon::Chip::newChip(title=><<"END");
$B bit integer to $N bits monotone mask.
END
     $c->inputBits         (qw(  i), $B);                                       # Input bus

     $c->integerToPointMask(qw(m i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputBits        (qw(o m));
  for my $i(0..$N)                                                              # Each position of mask
   {my %i = setBits($c, 'i', $i);
    my $s = $c->simulate(\%i, $i == 5 ? (svg=>"svg/integerToMontoneMask$B"):());
    is_deeply($s->steps, 3);

    my $r = $s->bint('o');                                                      # Mask values
    is_deeply($r, $i ? 1<<($i-1) : 0);                                          # Expected mask
   }
 }

monotoneMaskToInteger ($chip, $output, $input, %options)

Convert a monotone mask i to an output number r representing the location in the mask of the bit set to 1. If no such bit exists in the point then output in r is 0.

   Parameter  Description
1  $chip      Chip
2  $output    Output name
3  $input     Input mask
4  %options   Options

Example:

if (1)
 {my $B = 4;
  my $N = 2**$B-1;

  my $c = Silicon::Chip::newChip(title=><<"END");
$N bits monotone mask to $B bit integer
END
     $c->inputBits            ('i',     $N);

     $c->monotoneMaskToInteger(qw(m i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputBits           (qw(o m));

  for my $i(0..$N-1)                                                            # Each monotone mask
   {my %i = setBits($c, 'i', $i > 0 ? 1<<$i-1 : 0);
    my $s = $c->simulate(\%i,

      $i == 5 ? (svg=>"svg/monotoneMaskToInteger$B") : ());  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply($s->steps, 4);
    is_deeply($s->bint('m'), $i);
   }
 }

monotoneMaskToPointMask ($chip, $output, $input, %options)

Convert a monotone mask i to a point mask o representing the location in the mask of the first bit set to 1. If the monotone mask is all 0s then point mask is too.

   Parameter  Description
1  $chip      Chip
2  $output    Output name
3  $input     Input mask
4  %options   Options

Example:

if (1)
 {my $B = 4;

  my $c = newChip();
     $c->inputBits('m', $B);                                                    # Monotone mask

     $c->monotoneMaskToPointMask(qw(o m));                                      # Generate gates  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputBits('out', 'o');                                                # Point mask

  for my $i(0..$B)
   {my %m = $c->setBits('m', eval '0b'.(1 x $i).('0' x ($B-$i)));
    my $s = $c->simulate({%m});
    is_deeply($s->steps,                    2);
    is_deeply($s->bint('out'), $i ? (1<<($B-1)) / (1<<($i-1)) : 0);
   }
 }

integerToMonotoneMask ($chip, $output, $input, %options)

Convert an integer i of specified width to a monotone mask m. If the input integer is 0 then the mask is all zeroes. Otherwise the mask has i-1 leading zeroes followed by all ones thereafter.

   Parameter  Description
1  $chip      Chip
2  $output    Output name
3  $input     Input mask
4  %options   Options

Example:

if (1)
 {my $B = 4;
  my $N = 2**$B-1;

  my $c = Silicon::Chip::newChip(title=><<"END");
Convert $B bit integer to $N bit monotone mask
END
     $c->inputBits            ('i', $B);                                        # Input gates

     $c->integerToMonotoneMask(qw(m i));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputBits           (qw(o m));                                        # Output gates

  for my $i(0..$N)                                                              # Each position of mask
   {my %i = setBits($c, 'i', $i);                                               # The number to convert
    my $s = $c->simulate(\%i, $i == 2 ? (svg=>"svg/integerToMontoneMask$B"):());
    is_deeply($s->steps, 4);
    is_deeply($s->bint('o'), $i > 0 ? ((1<<$N)-1)>>($i-1)<<($i-1) : 0);# Expected mask
   }
 }

chooseWordUnderMask ($chip, $output, $input, $mask, %options)

Choose one of a specified number of words w, each of a specified width, using a point mask m placing the selected word in o. If no word is selected then o will be zero.

   Parameter  Description
1  $chip      Chip
2  $output    Output
3  $input     Inputs
4  $mask      Mask
5  %options   Options

Example:

if (1)
 {my $B = 3; my $W = 4;

  my $c = Silicon::Chip::newChip(title=><<"END");
Choose one of $W words of $B bits
END
     $c->inputWords         ('w',       $W, $B);
     $c->inputBits          ('m',       $W);

     $c->chooseWordUnderMask(qw(W w m));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputBits         (qw(o W));

  my %i = setWords($c, 'w', 0b000, 0b001, 0b010, 0b0100);
  my %m = setBits ($c, 'm', 1<<2);                                              # Choose the third word

  my $s = $c->simulate({%i, %m}, svg=>"svg/choose_${W}_$B");

  is_deeply($s->steps, 3);
  is_deeply($s->bint('o'), 0b010);
 }

findWord($chip, $output, $key, $words, %options)

Choose one of a specified number of words w, each of a specified width, using a key k. Return a point mask o indicating the locations of the key if found or or a mask equal to all zeroes if the key is not present.

   Parameter  Description
1  $chip      Chip
2  $output    Found point mask
3  $key       Key
4  $words     Words to search
5  %options   Options

Example:

if (1)
 {my $B = 3; my $W = 2**$B-1;

  my $c = Silicon::Chip::newChip(title=><<END);
Search $W words of $B bits
END
     $c->inputBits ('k',       $B);                                             # Search key
     $c->inputWords('w',       2**$B-1, $B);                                    # Words to search

     $c->findWord  (qw(m k w));                                                 # Find the word  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     $c->outputBits(qw(M m));                                                   # Output mask

  my %w = setWords($c, 'w', reverse 1..$W);

  for my $k(0..$W)                                                              # Each possible key
   {my %k = setBits($c, 'k', $k);

    my $s = $c->simulate({%k, %w}, $k == 3 ? (svg=>q(svg/findWord)) : ());  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    is_deeply($s->steps, 3);
    is_deeply($s->bint('M'),$k ? 2**($W-$k) : 0);
   }
 }

Simulate

Simulate the behavior of the chip given a set of values on its input gates.

setBits ($chip, $name, $value, %options)

Set an array of input gates to a number prior to running a simulation.

   Parameter  Description
1  $chip      Chip
2  $name      Name of input gates
3  $value     Number to set to
4  %options   Options

Example:

if (1)                                                                           # Compare two 4 bit unsigned integers 'a' > 'b' - the pins used to input 'a' must be alphabetically less than those used for 'b'
 {my $B = 4;                                                                    # Number of bits
  my $c = Silicon::Chip::newChip(title=><<"END");
$B Bit Compare
END
  $c->inputBits("a", $B);                                                       # First number
  $c->inputBits("b", $B);                                                       # Second number
  $c->nxor (n(e,$_), n(a,$_), n(b,$_)) for 1..$B-1;                             # Test each bit for equality
  $c->gt   (n(g,$_), n(a,$_), n(b,$_)) for 1..$B;                               # Test each bit pair for greater

  for my $b(2..$B)
   {$c->and(n(c,$b), [(map {n(e, $_)} 1..$b-1), n(g,$b)]);                      # Greater on one bit and all preceding bits are equal
   }
  $c->or    ("or",  [n(g,1), (map {n(c, $_)} 2..$B)]);                          # Any set bit indicates that 'a' is more than 'b'
  $c->output("out", "or");                                                      # Output 1 if a > b else 0


  my %a = $c->setBits('a', 0);                                                  # Number a  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


  my %b = $c->setBits('b', 0);                                                  # Number b  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


  my $s = $c->simulate({%a, %b, n(a,2)=>1, n(b,2)=>1});                         # Two equal numbers
  is_deeply($s->value("out"), 0);

  my $t = $c->simulate({%a, %b, n(a,2)=>1}, svg=>q(svg/Compare));               # Svg drawing of layout
  is_deeply($t->value("out"), 1);
 }
if (1)
 {my $B = 3; my $W = 4;

  my $c = Silicon::Chip::newChip(title=><<"END");
Choose one of $W words of $B bits
END
     $c->inputWords         ('w',       $W, $B);
     $c->inputBits          ('m',       $W);
     $c->chooseWordUnderMask(qw(W w m));
     $c->outputBits         (qw(o W));

  my %i = setWords($c, 'w', 0b000, 0b001, 0b010, 0b0100);

  my %m = setBits ($c, 'm', 1<<2);                                              # Choose the third word  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


  my $s = $c->simulate({%i, %m}, svg=>"svg/choose_${W}_$B");

  is_deeply($s->steps, 3);
  is_deeply($s->bint('o'), 0b010);
 }

setWords($chip, $name, @values)

Set an array of arrays of gates to an array of numbers prior to running a simulation.

   Parameter  Description
1  $chip      Chip
2  $name      Name of input gates
3  @values    Number of bits in each array element

Example:

if (1)
 {my $B = 3; my $W = 4;

  my $c = Silicon::Chip::newChip(title=><<"END");
Choose one of $W words of $B bits
END
     $c->inputWords         ('w',       $W, $B);
     $c->inputBits          ('m',       $W);
     $c->chooseWordUnderMask(qw(W w m));
     $c->outputBits         (qw(o W));


  my %i = setWords($c, 'w', 0b000, 0b001, 0b010, 0b0100);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  my %m = setBits ($c, 'm', 1<<2);                                              # Choose the third word

  my $s = $c->simulate({%i, %m}, svg=>"svg/choose_${W}_$B");

  is_deeply($s->steps, 3);
  is_deeply($s->bint('o'), 0b010);
 }

connectBits ($oc, $o, $ic, $i, %options)

Create a connection list connecting a set of output bits on the one chip to a set of input bits on another chip.

   Parameter  Description
1  $oc        First chip
2  $o         Name of gates on first chip
3  $ic        Second chip
4  $i         Names of gates on second chip
5  %options   Options

Example:

if (1)                                                                            # Install one chip inside another chip, specifically one chip that performs NOT is installed once to flip a value
 {my $i = newChip(name=>"not");
     $i-> inputBits('i',     1);
     $i->   notBits(qw(n i));
     $i->outputBits(qw(o n));

  my $o = newChip(name=>"outer");
     $o->inputBits('i', 1); $o->outputBits(qw(n i));
     $o->inputBits('I', 1); $o->outputBits(qw(N I));


  my %i = connectBits($i, 'i', $o, 'n');  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


  my %o = connectBits($i, 'o', $o, 'I');  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  $o->install($i, {%i}, {%o});
  my %d = $o->setBits('i', 1);
  my $s = $o->simulate({%d}, printOff=>"dump/not1", svg=>"svg/not1");

  is_deeply($s->steps,  2);
  is_deeply($s->values, {"(not 1 n_1)"=>0, "i_1"=>1, "N_1"=>0 });
 }

connectWords($oc, $o, $ic, $i, $words, $bits, %options)

Create a connection list connecting a set of words on the outer chip to a set of words on the inner chip.

   Parameter  Description
1  $oc        First chip
2  $o         Name of gates on first chip
3  $ic        Second chip
4  $i         Names of gates on second chip
5  $words     Number of words to connect
6  $bits      Options
7  %options

Example:

if (1)                                                                           # Install one chip inside another chip, specifically one chip that performs NOT is installed three times sequentially to flip a value
 {my $i = newChip(name=>"not");
     $i-> inputWords('i', 1, 1);
     $i->   notWords(qw(n i));
     $i->outputWords(qw(o n));

  my $o = newChip(name=>"outer");
     $o->inputWords('i', 1, 1); $o->output(nn('n', 1, 1), nn('i', 1, 1));
     $o->inputWords('I', 1, 1); $o->output(nn('N', 1, 1), nn('I', 1, 1));


  my %i = connectWords($i, 'i', $o, 'n', 1, 1);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


  my %o = connectWords($i, 'o', $o, 'I', 1, 1);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  $o->install($i, {%i}, {%o});
  my %d = $o->setWords('i', 1);
  my $s = $o->simulate({%d}, printOff=>"dump/not1", svg=>"svg/not1");

  is_deeply($s->steps,  2);
  is_deeply($s->values, { "(not 1 n_1_1)" => 0, "i_1_1" => 1, "N_1_1" => 0 });
 }

Silicon::Chip::Simulation::value($simulation, $name, %options)

Get the value of a gate as seen in a simulation

   Parameter    Description
1  $simulation  Chip
2  $name        Gate
3  %options     Options

Example:

if (1)                                                                          # Internal input gate
 {my $c = newChip();
     $c->input ('i');                                                           # Input
     $c->input ('j');                                                           # Internal input which we will connect to later
     $c->output(qw(o j));                                                       # Output

     $c->connectInput(qw(j i));

  my $s = $c->simulate({i=>1});
  is_deeply($s->steps, 1);
  is_deeply($s->value("j"), undef);
  is_deeply($s->value("o"), 1);
 }

if (1)                                                                           # Internal input gate
 {my @n = qw(3 2 1 2 3);
  my $c = newChip();
     $c->words('i', 2, @n);                                                     # Input
     $c->outputWords(qw(o i));                                                  # Output
  my $s = $c->simulate({});
  is_deeply($s->steps, 2);
  is_deeply([$s->wordsToInteger("i")], [@n]);
 }

if (1)                                                                           # Internal input gate
 {my @n = qw(3 2 1 2 3);
  my $c = newChip();
     $c->words('i', 2, @n);                                                     # Input
     $c->outputWords(qw(o i));                                                  # Output
  my $s = $c->simulate({});
  is_deeply($s->steps, 2);
  is_deeply([$s->wordsToInteger("i")], [@n]);
 }

Silicon::Chip::Simulation::bint ($simulation, $output, %options)

Represent the state of bits in the simulation results as an unsigned binary integer.

   Parameter    Description
1  $simulation  Chip
2  $output      Name of gates on bus
3  %options     Options

Example:

if (1)
 {my $W = 8;
  my $i = newChip(name=>"not");
     $i->inputBits('i',      $W);
     $i->notBits  (qw(n i));
     $i->outputBits(qw(o n));

  my $o = newChip(name=>"outer");
     $o->inputBits ('a',     $W);
     $o->outputBits(qw(A a));
     $o->inputBits ('b',     $W);
     $o->outputBits(qw(B b));

  my %i = connectBits($i, 'i', $o, 'A');
  my %o = connectBits($i, 'o', $o, 'b');
  $o->install($i, {%i}, {%o});

  my %d = setBits($o, 'a', 0b10110);
  my $s = $o->simulate({%d}, svg=>q(svg/not));
  is_deeply($s->bint('B'), 0b11101001);
 }

Silicon::Chip::Simulation::wordsToInteger ($simulation, $output, %options)

Represent the state of words in the simulation results as an array of unsigned binary integer.

   Parameter    Description
1  $simulation  Chip
2  $output      Name of gates on bus
3  %options     Options

Example:

if (1)
 {my @b = ((my $W = 4), (my $B = 3));

  my $c = newChip();
     $c->inputWords ('i',      @b);
     $c->outputWords(qw(o i));

  my %d = setWords($c, 'i', 0b000, 0b001, 0b010, 0b011);
  my $s = $c->simulate({%d}, svg=>"svg/words$W");

  is_deeply([$s->wordsToInteger('o')], [0..3]);
  is_deeply([$s->wordXToInteger('o')], [10, 12, 0]);
 }

Silicon::Chip::Simulation::wordXToInteger ($simulation, $output, %options)

Represent the state of words in the simulation results as an array of unsigned binary integer.

   Parameter    Description
1  $simulation  Chip
2  $output      Name of gates on bus
3  %options     Options

Example:

if (1)
 {my @b = ((my $W = 4), (my $B = 3));

  my $c = newChip();
     $c->inputWords ('i',      @b);
     $c->outputWords(qw(o i));

  my %d = setWords($c, 'i', 0b000, 0b001, 0b010, 0b011);
  my $s = $c->simulate({%d}, svg=>"svg/words$W");

  is_deeply([$s->wordsToInteger('o')], [0..3]);
  is_deeply([$s->wordXToInteger('o')], [10, 12, 0]);
 }

simulate($chip, $inputs, %options)

Simulate the action of the logic gates on a chip for a given set of inputs until the output value of each logic gate stabilizes.

   Parameter  Description
1  $chip      Chip
2  $inputs    Hash of input names to values
3  %options   Options

Example:

if (1)
 {my $i = newChip(name=>"inner");
     $i->input ("Ii");
     $i->not   ("In", "Ii");
     $i->output( "Io", "In");

  my $o = newChip(name=>"outer");
     $o->input ("Oi1");
     $o->output("Oo1", "Oi1");
     $o->input ("Oi2");
     $o->output("Oo2", "Oi2");
     $o->input ("Oi3");
     $o->output("Oo3", "Oi3");
     $o->input ("Oi4");
     $o->output("Oo",  "Oi4");

  $o->install($i, {Ii=>"Oo1"}, {Io=>"Oi2"});
  $o->install($i, {Ii=>"Oo2"}, {Io=>"Oi3"});
  $o->install($i, {Ii=>"Oo3"}, {Io=>"Oi4"});


  my $s = $o->simulate({Oi1=>1}, printOff=>"dump/not3", svg=>"svg/not3");  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  is_deeply($s->value("Oo"), 0);
  is_deeply($s->steps,       4);
 }

Hash Definitions

Silicon::Chip Definition

Chip description

Output fields

gateSeq

Gate sequence number - this allows us to display the gates in the order they were defined ti simplify the understanding of drawn layouts

gates

Gates in chip

installs

Chips installed within the chip

name

Name of chip

sizeBits

Sizes of buses

sizeWords

Sizes of buses

title

Title if known

Private Methods

AUTOLOAD($chip, @options)

Autoload by logic gate name to provide a more readable way to specify the logic gates on a chip.

   Parameter  Description
1  $chip      Chip
2  @options   Options

Index

1 andBits - and a bus made of bits.

2 andWords - and a bus made of words to produce a single word.

3 andWordsX - and a bus made of words by and-ing the corresponding bits in each word to make a single word.

4 AUTOLOAD - Autoload by logic gate name to provide a more readable way to specify the logic gates on a chip.

5 bits - Create a bus set to a specified number.

6 chooseFromTwoWords - Choose one of two words based on a bit.

7 chooseWordUnderMask - Choose one of a specified number of words w, each of a specified width, using a point mask m placing the selected word in o.

8 compareEq - Compare two unsigned binary integers of a specified width returning 1 if they are equal else 0.

9 compareGt - Compare two unsigned binary integers and return 1 if the first integer is more than b else 0.

10 compareLt - Compare two unsigned binary integers a, b of a specified width.

11 connectBits - Create a connection list connecting a set of output bits on the one chip to a set of input bits on another chip.

12 connectInput - Connect a previously defined input gate to the output of another previously gate on the same chip.

13 connectWords - Create a connection list connecting a set of words on the outer chip to a set of words on the inner chip.

14 enableWord - Output a word or zeros depending on a choice bit.

15 findWord - Choose one of a specified number of words w, each of a specified width, using a key k.

16 gate - A logic gate chosen from and|continue|gt|input|lt|nand|nor|not|nxor|one|or|output|xor|zero.

17 inputBits - Create an input bus made of bits.

18 inputWords - Create an input bus made of words.

19 install - Install a chip within another chip specifying the connections between the inner and outer chip.

20 integerToMonotoneMask - Convert an integer i of specified width to a monotone mask m.

21 integerToPointMask - Convert an integer i of specified width to a point mask m.

22 monotoneMaskToInteger - Convert a monotone mask i to an output number r representing the location in the mask of the bit set to 1.

23 monotoneMaskToPointMask - Convert a monotone mask i to a point mask o representing the location in the mask of the first bit set to 1.

24 n - Gate name from single index.

25 nandBits - nand a bus made of bits.

26 newChip - Create a new chip.

27 nn - Gate name from double index.

28 norBits - nor a bus made of bits.

29 notBits - Create a not bus made of bits.

30 notWords - Create a not bus made of words.

31 orBits - or a bus made of bits.

32 orWords - or a bus made of words to produce a single word.

33 orWordsX - or a bus made of words by or-ing the corresponding bits in each word to make a single word.

34 outputBits - Create an output bus made of bits.

35 outputWords - Create an output bus made of words.

36 pointMaskToInteger - Convert a mask i known to have at most a single bit on - also known as a point mask - to an output number a representing the location in the mask of the bit set to 1.

37 print - Dump the logic gates present on a chip.

38 printSvg - Dump the logic gates on a chip as an Scalar Vector Graphics drawing to help visualize the structure of the chip.

39 setBits - Set an array of input gates to a number prior to running a simulation.

40 setSizeBits - Set the size of a bits bus.

41 setSizeWords - Set the size of a bits bus.

42 setWords - Set an array of arrays of gates to an array of numbers prior to running a simulation.

43 Silicon::Chip::Simulation::bint - Represent the state of bits in the simulation results as an unsigned binary integer.

44 Silicon::Chip::Simulation::print - Print simulation results as text.

45 Silicon::Chip::Simulation::printSvg - Print simulation results as svg.

46 Silicon::Chip::Simulation::value - Get the value of a gate as seen in a simulation

47 Silicon::Chip::Simulation::wordsToInteger - Represent the state of words in the simulation results as an array of unsigned binary integer.

48 Silicon::Chip::Simulation::wordXToInteger - Represent the state of words in the simulation results as an array of unsigned binary integer.

49 simulate - Simulate the action of the logic gates on a chip for a given set of inputs until the output value of each logic gate stabilizes.

50 words - Create a word bus set to specified numbers.

Installation

This module is written in 100% Pure Perl and, thus, it is easy to read, comprehend, use, modify and install via cpan:

sudo cpan install Silicon::Chip

Author

philiprbrenan@gmail.com

http://www.appaapps.com

Copyright

Copyright (c) 2016-2023 Philip R Brenan.

This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.