Add diagrams and pictures
[clump.git] / bigone.pl
1 #!/usr/bin/perl
2 use v5.14;
3 use warnings;
4 use lib '.';
5
6 use asm;
7
8 sub update_leds {
9 my ($x) = @_;
10 route $x + 0, $x + 1, 4;
11 route $x + 1, $x + 2, 3;
12 route $x + 2, $x + 3, 2;
13 route $x + 3, $x + 4, 1;
14 }
15
16 sub xori {
17 my ($addrA, $imm, $addrC) = @_;
18 storei 42, $imm;
19 xor_ $addrA, 42, $addrC;
20 }
21
22 sub andi {
23 my ($addrA, $imm, $addrC) = @_;
24 storei 42, $imm;
25 and_ $addrA, 42, $addrC;
26 }
27
28 # we want everyone to have
29 #
30 # own quadrant at mem[0]
31 # east quadrant at mem[11]
32 # south quadrant at mem[12]
33 # SE quadrant at mem[13]
34
35 my $q_east = 11;
36 my $q_south = 12;
37 my $q_SE = 13;
38
39 chip_select 4, sub { storei 0, 0x247 }; # glider
40 chip_select $_, sub { ledi $_ } for 1, 2, 4, 8;
41
42
43 update_leds 0;
44
45 chip_select 1, sub { route 0, 11 };
46 chip_select 2, sub { route 11, 12 };
47 chip_select 4, sub { route 12, 13 };
48
49 chip_select 2, sub { route 0, 13 };
50 chip_select 4, sub { route 13, 12 };
51 chip_select 8, sub { route 12, 11 };
52
53 chip_select 4, sub { route 0, 11 };
54 chip_select 8, sub { route 11, 12 };
55 chip_select 1, sub { route 12, 13 };
56
57 chip_select 8, sub { route 0, 13 };
58 chip_select 1, sub { route 13, 12 };
59 chip_select 2, sub { route 12, 11 };
60
61
62 sub news_to_mem {
63 my ($dir, $mem) = @_;
64 alu3 alu_zero, alu_select_f, 0, 0, $mem, flag_news($dir), flag_zero
65 }
66
67 my $and_AB = alu_of_function { $a & $b };
68
69 sub compute_neighbour {
70 my ($dest, $dir, $mask, $other) = @_;
71 storei $dest, $mask;
72 alu3 $and_AB, $and_AB, 0, $dest, $dest, flag_zero, flag_zero;
73 news_to_mem $dir, $dest;
74
75 storei $dest + 1, 0xFFFF - $mask;
76 alu3 $and_AB, $and_AB, $other, $dest + 1, $dest + 1, flag_zero, flag_zero;
77 alu3 alu_zero, alus_addAF, $dest, 0, $dest, flag_news($dir), flag_zero
78 }
79
80 # N neighbour
81 compute_neighbour 1, 0, 0x0FFF, $q_south;
82 # E neighbour
83 compute_neighbour 2, 1, 0xEEEE, $q_east;
84 # S neighbour
85 compute_neighbour 3, 2, 0xFFF0, $q_south;
86 # W neighbour
87 compute_neighbour 4, 3, 0x7777, $q_east;
88
89 sub compute_diagonal_neighbour {
90 my ($dest, $dir, @masks) = @_;
91 die 'expected exactly 4 @masks' unless @masks == 4;
92 storei $dest, $masks[0];
93 alu3 $and_AB, alu_select_a, 0, $dest, 0, flag_zero, flag_zero;
94 news_to_mem $dir, $dest;
95
96 for my $quad (1 .. 3) {
97 storei $dest + 1, $masks[$quad];
98 alu3 $and_AB, alu_select_a, 10 + $quad, $dest + 1, 10 + $quad, flag_zero, flag_zero;
99 alu3 alu_zero, alus_addAF, $dest, 0, $dest, flag_news($dir), flag_zero;
100 }
101 }
102
103 #update_leds $q_SE;
104
105 # NW neighbour
106 compute_diagonal_neighbour 5, 4, 0x0777, 0x0888, 0x7000, 0x8000;
107 #update_leds 5;
108 # NE neighbour
109 compute_diagonal_neighbour 6, 5, 0x0EEE, 0x0111, 0xE000, 0x1000;
110 #update_leds 6;
111 # SE neighbour
112 compute_diagonal_neighbour 7, 6, 0xEEE0, 0x1110, 0x000E, 0x0001;
113 #update_leds 7;
114 # SW neighbour (DODGY)
115 compute_diagonal_neighbour 8, 7, 0x7770, 0x8880, 0x0007, 0x0008;
116 #update_leds 8;
117
118 sub flag_to_memory {
119 my ($address, $flag) = @_;
120 alu3 alu_zero, alu_select_f, 0, 0, $address, $flag, flag_zero;
121 }
122
123 # now we add bits mem[1] .. mem[8]
124 # result should be mem[1] .. mem[3] (we don't distinguish 8 from 0)
125 my $F = 1;
126
127 # add 1 and 2, 3 and 4, 5 and 6, 7 and 8
128 for my $x (1, 3, 5, 7) {
129 add $x, $x + 1, $x, $F;
130 flag_to_memory $x + 1, $F;
131 }
132
133 # add 12 and 34, 56 and 78
134 for my $x (1, 5) {
135 add $x, $x + 2, $x, $F;
136 addC $x + 1, $x + 3, $x + 1, $F;
137 flag_to_memory $x + 2, $F;
138 }
139
140 # add 12 and 56
141 add 1, 5, 1, $F;
142 addC 2, 6, 2, $F;
143 # F = F | 3 | 7
144 alu3 alu_or, alu_select_a, 3, 7, 3, $F, $F;
145
146 # should a new cell be born here? (do we have 3 neighbours?)
147 sub alu_birth { alu_of_function {; $a && $b && !$_ } }
148
149 # should a living cell survive here? (do we have 2 or 3 neighbours?)
150 sub alu_survival { alu_of_function {; $a && !$_ } }
151
152 # compute the state of this cell at the next tick
153 sub alu_step { alu_of_function {; $_ & ($a | $b) } }
154
155 # read from memory 1, and with memory 2 and not F, write into memory 1 (= birth-p)
156 alu3 alu_zero, alu_birth, 1, 2, 1, $F, flag_zero;
157 # read from memory 2, and with flag not F, write into flag F (= survive-p)
158 alu3 alu_survival, alu_select_a, 2, 0, 2, $F, $F;
159 # read from memory 0, memory 1, and flag F, write F and (mem0 or mem1) into memory 0
160 alu3 alu_zero, alu_step, 0, 1, 0, $F, $F; # also zeroes out flag F
This page took 0.032716 seconds and 4 git commands to generate.