OpenCores
URL https://opencores.org/ocsvn/ssbcc/ssbcc/trunk

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [example/] [GameOfLife/] [hdl/] [uc/] [propagate.s] - Blame information for rev 11

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sinclairrf
; propagate.s
2
; Copyright 2012-2013, Sinclair R.F., Inc.
3
;
4
; Propagate state for Conway's Game of Life, SSBCC.9x8 implementation
5
;
6
; Method:  As each successive line of the current state is processed, maintain
7
; copies of the preceding, current, and next lines.  This provides a straight
8
; forward way to accommodate the "wrap" status.
9
 
10
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11
;
12
; Propagate the state.
13
; ( - )
14
;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
17
.function propagate
18
 
19
  ; Fill the middle line buffer with zeros or the last line of the image (if in
20
  ; wrap mode).
21
  ${C_N_MEM_LINES-1} .outport(O_ADDR_LINE)
22
  line_curr
23
  .fetchvalue(cmd_wrap) .callc(propagate__read_line)
24
  .fetchvalue(cmd_wrap) 0= .callc(propagate__zero_buffer)
25
 
26
 
27
  ; Fill the last line buffer with the first line of the image
28
  0x00 .outport(O_ADDR_LINE)
29
  .call(propagate__read_line,line_next)
30
 
31
  ;
32
  ; Compute the new image.
33
  ;
34
 
35
  ; ( - ix_line )
36
  0x00 :loop_outer
37
 
38
    ; Copy the middle and last line buffers to the first and middle line
39
    ; buffers respectively.
40
    line_prev .call(propagate__copy_line,line_curr)
41
    line_curr .call(propagate__copy_line,line_next)
42
 
43
    ; If this is is not the last line or if wrapping is commanded, then read the
44
    ; next line, otherwise fill the buffer with zeros.
45
    ; ( ix_line - ix_line (ix_line+1)&(mask) )
46
    dup 1+ O_ADDR_LINE ${C_N_MEM_LINES-1} & .outport
47
    ; ( ix_line (ix_line+1)&(mask) - ix_line )
48
    .fetchvalue(cmd_wrap) or .jumpc(do_read)
49
      .call(propagate__zero_buffer,line_next) .jump(do_read_done)
50
    :do_read
51
      .call(propagate__read_line,line_next)
52
    :do_read_done
53
 
54
    ; write the line number as the upper portion of the write address
55
    ; ( ix_line - ix_line )
56
    O_ADDR_LINE .outport
57
 
58
    ; Compute and store the new state of the current line.
59
    .call(propagate__line)
60
 
61
    ; ( ix_line - [(ix_line+1)&(mask)] )
62
    1+ ${C_N_MEM_LINES-1} & .jumpc(loop_outer,nop) drop
63
 
64
  .return
65
 
66
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
67
;
68
; Copy the current line buffer to the previous line buffer.
69
; ( u_prev u_curr - )
70
;
71
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
72
 
73
.function propagate__copy_line
74
  ; ( - n_remaining )
75
  ${(C_N_MEM_WORDS+2)-1} :loop_copy
76
    ; ( n_remaining - ) r: ( - n_remaining )
77
    >r
78
    ; ( u_prev+n u_curr+n - u_prev+n+1 u_curr+n+1 )
79
    .fetch+(ram) >r swap .store+(ram) r>
80
    ; ( - [n_remaining-1] ) r: ( n_remaining - )
81
    r> .jumpc(loop_copy,1-) drop
82
  ; ( u_prev+N+2 u_curr+N+2 - )
83
  drop .return(drop)
84
 
85
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
86
;
87
; Compute and store the new state of the current line.
88
; ( - )
89
;
90
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
91
 
92
.function propagate__line
93
 
94
  ; Initialize the processing state.
95
  ; ( - 0 u_left u_here ) r: ( - u_index u_mask )
96
 
97
  0x80 >r
98
 
99
  .call(propagate__fetch_triple)
100
  .call(propagate__fetch_triple)
101
  r> drop r>
102
 
103
  :loop_outer >r
104
    r@ 1- .outport(O_ADDR_WORD)
105
    ; Push the next 8-bit candidate value onto the return stack.
106
    ; r: ( - u_8bit )
107
 
108
    0x01 :loop_inner
109
      ; Drop the oldest triple and bring in the triple from the right.
110
      ; ( u_left_old u_curr_old u_next_old - u_left_new=u_curr_old u_curr_new=u_next_old u_next_new )
111
      >r swap drop r> .call(propagate__fetch_triple)
112
      ; Compute the new bit based on these surrounding bits
113
      ; ( u_left u_curr u_next - u_left u_curr u_next u_new_bit )
114
      .call(propagate__new_bit)
115
      ; Shift the bitmask left 1 bit and finish the loop if the ones bit has rolled off the left.
116
      r> <<0 .jumpc(loop_inner,nop) drop
117
      r> .outport(O_BUFFER)
118
    r> 1+ dup ${(C_N_MEM_WORDS+2)-1} - 0<> .jumpc(loop_outer) drop
119
 
120
  .return
121
 
122
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
123
;
124
; Compute the new state of a pixel based on the 3x3 grid of pixels centered at
125
; the candidate pixel.
126
; ( u_prev u_curr u_next - u_prev u_curr u_next u_new )
127
;
128
; Rules:
129
;   1.  Live pixels with fewer than 2 live neighbors die.
130
;   2.  Live pixels with 2 or 3 live neighbors stay alive.
131
;   3.  Live pixels with more than 3 live neighbors die.
132
;   4.  Dead pixels with exactly 3 live neighbors come to life.
133
;
134
; Method used here:
135
;   1.  Count all live pixels in the 3x3 grid, including the candidate pixel.
136
;   2.  Get the alive/dead status of the candidate pixel.
137
;   3.  If 3 pixels are alive or if 4 pixels are alive and the candidate pixel
138
;       is alive, then propagate a live pixel.
139
;
140
; Note:
141
;   1.  If exactly 3 pixels are alive, then either (1) the cell is alive and
142
;       exactly two neighbors are alive or (2) the cell is dead and exactly 3
143
;       neighbors are alive.  In either case, the cell will either stay alive
144
;       or become alive.
145
;
146
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
147
 
148
.function propagate__new_bit
149
 
150
  ; Put the candidate pixels status on the return stack
151
  ; ( u_curr u_next - u_curr u_next ) r: ( - f_this_bit_set )
152
  over 0x02 & 0<> >r
153
 
154
  ; ( u_next - ) r: ( - u_next )
155
  >r
156
 
157
  ; ( u_prev u_curr - u_prev u_curr n_prev )
158
  over .fetch(nBitsSet)
159
 
160
  ; ( u_curr n_prev - u_curr n_prev+n_curr )
161
  over .fetch(nBitsSet) +
162
 
163
  ; ( n_prev+n_curr - u_next n_total=n_prev+n_curr+n_next ) r: ( u_next - )
164
  r> swap over .fetch(nBitsSet) +
165
 
166
  ; ( n_total - u_bit ) r: ( f_this_bit_set - )
167
  dup 3 - 0= swap 4 - 0= r> & or 0x01
168
 
169
  .return(&)
170
 
171
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
172
;
173
; Read a line into the specified buffer.
174
; ( u_line_buffer - )
175
;
176
; Method:  Copy the contents of the current line to the specified buffer.  Then,
177
; if wrapping is turned on, copy the first and last elements of the line to the
178
; end and start of the buffer respectively.
179
;
180
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
181
 
182
.function propagate__read_line
183
 
184
  ; Set the last element of the buffer to zero.
185
  ; ( u_line_buffer - u_line_buffer+1+C_N_MEM_WORDS-1 )
186
  ${C_N_MEM_WORDS+2-1) +
187
 
188
 
189
  ;
190
  ; Copy the current line to the buffer.
191
  ; ( u_line_buffer+1+C_N_MEM_WORDS-1 - u_line_buffer )
192
  ;
193
 
194
  ; Initialize the index/count for the transfer
195
  ; ( - u_ix_word )
196
  ${C_N_MEM_WORDS-1} :loop
197
 
198
    ; read the next word
199
    ; ( u_ix_word - u_word ) r: ( - u_ix_word )
200
    .outport(O_ADDR_WORD,>r) .inport(I_BUFFER)
201
 
202
    ; store it in the buffer
203
    ; ( u_line_buffer+? u_word - u_line_buffer+?-1 )
204
    swap .store-(ram)
205
 
206
    ; Do the loop iteration
207
    ; ( - [u_ix_word-1] ) r:( u_ix_word - )
208
    r> .jumpc(loop,1-) drop
209
 
210
  ; If wrap mode is turned on, then copy the first and last entries in the line
211
  ; to the last and first entries in the buffer respectively.
212
  ; Effect is either
213
  ;   ( u_line_buffer - u_line_buffer )
214
  ; or
215
  ;   ( u_line_buffer - u_word )
216
  .fetchvalue(cmd_wrap) 0= .jumpc(no_wrap)
217
    ; Copy the first entry in the line to the last entry in the buffer.
218
    ; ( u_line_buffer - u_line_buffer u_line_buffer+(C_N_MEM_WORDS+1)-1 )
219
    dup 1+ .fetch(ram) over ${(C_N_MEM_WORDS+2)-1} + .store-(ram)
220
    ; Copy the last entry in the line to the first entry in the buffer.
221
    ; ( u_line_buffer u_line_buffer+(C_N_MEM_WORDS+1)-1 - u_word )
222
    .fetch(ram) swap .store(ram)
223
  :no_wrap
224
 
225
  ; Return and clean up the data stack.
226
  ; ( u_XXX - )
227
  .return(drop)
228
 
229
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
230
;
231
; Fill the specified line buffer with all zeros.
232
; ( u_line - )
233
;
234
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
235
 
236
.function propagate__zero_buffer
237
  ${(C_N_MEM_WORDS+2)-1} :loop_curr_fill_zero >r 0 swap .store+(ram) r> .jumpc(loop_curr_fill_zero,1-) drop
238
  .return(drop)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.