Adding ICE40 FPGA synthesizer

This commit is contained in:
Brad Nelson
2025-11-14 22:00:32 -08:00
parent 134cc8215b
commit 4752b5e83d
9 changed files with 1302 additions and 2 deletions

View File

@ -0,0 +1,44 @@
\ Copyright 2025 Bradley D. Nelson
\
\ Licensed under the Apache License, Version 2.0 (the "License");
\ you may not use this file except in compliance with the License.
\ You may obtain a copy of the License at
\
\ http://www.apache.org/licenses/LICENSE-2.0
\
\ Unless required by applicable law or agreed to in writing, software
\ distributed under the License is distributed on an "AS IS" BASIS,
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\ See the License for the specific language governing permissions and
\ limitations under the License.
vocabulary flyclasses flyclasses definitions
0 value classes
1 value methods
0 value dispatch
0 value implementing
: flyclass create classes , 1 +to classes does> @ ;
: method& ( m cls -- a ) classes mod methods * + cells dispatch + ;
: accrued ( -- a ) 0 implementing method& ;
: method create methods , 1 +to methods does> @ over method& @ execute ;
: implementation ( cls -- ) to implementing ;
: >min ( a -- n ) cell+ @ ; : >max ( a -- a ) @ ;
: >below ( a -- a ) 2 cells + @ ; : >above ( a -- a) 3 cells + @ ;
: field ( min max -- "name" )
create 2dup , , accrued @ , swap - 1+ accrued @ * dup , accrued !
does> >r r@ >above mod r@ >below / r> >min + ;
: doput ( n o -- o "name" ) >r dup r@ >below mod swap r@ >above / r@ >above * +
swap r@ >max min r@ >min - r> >below * + ;
: put ( n o -- o "name" ) ' >body postpone literal postpone doput ; immediate
: extension ( cls -- ) 0 swap method& accrued methods cells cmove ;
: initiate here to dispatch
classes 1- for classes , methods 1- 1- for ['] abort , next next ;
: do:: ( o cls m -- ) swap method& @ execute ;
: :: ( o cls "name" -- ) ' >body @ postpone literal postpone do:: ; immediate
: m: ' >body @ :noname ;
: ;m postpone ; swap implementing method& ! ; immediate
forth definitions

16
pico-ice/ice40/ice40.fs Normal file
View File

@ -0,0 +1,16 @@
\ Copyright 2025 Bradley D. Nelson
\
\ Licensed under the Apache License, Version 2.0 (the "License");
\ you may not use this file except in compliance with the License.
\ You may obtain a copy of the License at
\
\ http://www.apache.org/licenses/LICENSE-2.0
\
\ Unless required by applicable law or agreed to in writing, software
\ distributed under the License is distributed on an "AS IS" BASIS,
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\ See the License for the specific language governing permissions and
\ limitations under the License.
needs ice40_synthesis.fs
needs ice40_storage.fs

View File

@ -0,0 +1,72 @@
\ Copyright 2025 Bradley D. Nelson
\
\ Licensed under the Apache License, Version 2.0 (the "License");
\ you may not use this file except in compliance with the License.
\ You may obtain a copy of the License at
\
\ http://www.apache.org/licenses/LICENSE-2.0
\
\ Unless required by applicable law or agreed to in writing, software
\ distributed under the License is distributed on an "AS IS" BASIS,
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\ See the License for the specific language governing permissions and
\ limitations under the License.
needs ice40_layout.fs
ice40 synthesis definitions
1 value tx
1 value ty
0 value tb
: PLACE ( x y -- ) to ty to tx 0 to tb ;
: PLACE-OUTPUT ( -- o ) tx ty tb Output .create ;
: USED? ( -- f ) place-output .isLogic? 0= if -1 exit then
place-output .getLogic 0<> ;
: ADVANCE
tb 7 < if 1 +to tb exit then
ty cells-height 1- < if 1 +to ty 0 to tb exit then
tx cells-width 1- < assert
1 +to tx 0 to ty 0 to tb
;
: allot-lut ( -- o )
begin used? while
advance
repeat
place-output
;
: ROUTE! { src dst -- }
src dst route 0= if
." ERROR UNABLE TO ROUTE!!!" cr
." SOURCE: " src .print cr
." DESTINATION: " dst .print cr
123 throw
then
src dst route.
;
: LUT4 { i0 i1 i2 i3 tbl -- o }
allot-lut { o }
tbl o .setLogic
i0 0 o .getInput route!
i1 1 o .getInput route!
i2 2 o .getInput route!
i3 3 o .getInput route!
o
;
: FFL ( -- o )
allot-lut { o }
$aaaa o .setLogic
-1 o .dffEnableBit .setBit
o
;
: FF! ( v ff -- ) 0 swap .getInput route! ;
forth definitions

View File

@ -0,0 +1,65 @@
\ Copyright 2025 Bradley D. Nelson
\
\ Licensed under the Apache License, Version 2.0 (the "License");
\ you may not use this file except in compliance with the License.
\ You may obtain a copy of the License at
\
\ http://www.apache.org/licenses/LICENSE-2.0
\
\ Unless required by applicable law or agreed to in writing, software
\ distributed under the License is distributed on an "AS IS" BASIS,
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\ See the License for the specific language governing permissions and
\ limitations under the License.
vocabulary ice40 ice40 definitions
( For the 5k model in the pico-ice )
26 constant cells-width
32 constant cells-height
6 constant bram-column1
19 constant bram-column2
692 constant cram-bank-width
336 constant cram-height-lower
176 constant cram-height-upper
cram-height-lower cram-height-upper + constant cram-height
cram-bank-width 2* cram-height * 8 / constant cram-size
160 constant bram-width-lower
80 constant bram-width-upper
256 constant bram-bank-height
128 constant bram-chunk-size
( For the SG48 package in the pico-ice )
48 constant pinmax pinmax 1+ 2* cells constant pinsize
create pinmap pinsize allot pinmap pinsize 0 fill
0 value pinpos : x 1 +to pinpos ; : p ( p# -- ) pinpos swap cells pinmap + ! x ;
: pin#s ( p# -- x y b ) cells pinmap + @ 24 /mod >r 1+ r> 2 /mod 1 xor 31 * swap ;
\ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 COLUMN
\ | | | | | | | | | | | | | | | | | | | | | | | |
x x x 39 p 40 p 41 p x 42 p 43 p x x x 37 p x x 32 p 28 p 26 p 23 p x x x x x \ 0 TOP
x x x x x x x 38 p 36 p x x 35 p 34 p x x 31 p x 27 p 25 p x x x x x \ 1
\ | | | | | | | | | | | | | | | | | | | | | | | | PIN#
x x x x 46 p 47 p 48 p 2 p 4 p x x x x x 9 p 10 p 11 p 12 p 13 p x x x 14 p 15 p \ 0
x x x x x 44 p 45 p x 3 p x x x 6 p x x x x 21 p 20 p x 19 p 18 p 17 p 16 p \ 1 BOT
( Whole bitmap for config ram )
cram-size allocate throw constant cram
cram cram-size 0 fill
( Clear, read, and write as a bitmap )
: clear cram cram-size 0 fill ;
: cr& ( x y -- a*8 ) cram-height-lower /mod if
cram-height-upper 1- swap - cram-height-lower +
then cram-bank-width * >r
cram-bank-width 2 - /mod if
cram-bank-width 1- swap - 2 - cram-bank-width cram-height * +
then r> + ;
: bit! ( b pos v -- v ) >r 1 swap 7 swap - lshift dup invert r> and >r swap 0<> and r> or ;
: cram! ( b x y -- ) cr& 8 /mod cram + dup >r c@ bit! r> c! ;
: cram@ ( x y -- b ) cr& 8 /mod cram + c@ swap 7 swap - rshift 1 and 0<> ; ( UNTESTED )
forth definitions

View File

@ -0,0 +1,795 @@
\ Copyright 2025 Bradley D. Nelson
\
\ Licensed under the Apache License, Version 2.0 (the "License");
\ you may not use this file except in compliance with the License.
\ You may obtain a copy of the License at
\
\ http://www.apache.org/licenses/LICENSE-2.0
\
\ Unless required by applicable law or agreed to in writing, software
\ distributed under the License is distributed on an "AS IS" BASIS,
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\ See the License for the specific language governing permissions and
\ limitations under the License.
needs ice40_config.fs
needs flyclasses.fs
ice40 definitions
vocabulary synthesis synthesis definitions
also flyclasses
54 constant logic-width
42 constant ram-width
logic-width ram-width - constant logicram-diff
flyclass CramBit
flyclass CramCell
flyclass Output
flyclass Input
flyclass Input0
flyclass Input1
flyclass Input2
flyclass Input3
flyclass LocalG
flyclass LocalG0
flyclass LocalG1
flyclass LocalG2
flyclass LocalG3
flyclass IOLocalG
flyclass IOLocalG0
flyclass IOLocalG1
flyclass SpanWire
flyclass Sp4HR
flyclass Sp4VB
flyclass Sp12HR
flyclass Sp12VB
flyclass IOPin
flyclass IOInput
flyclass IOOutput
flyclass IOOutput0
flyclass IOOutput1
flyclass IOEnable
flyclass IOFabOutput
flyclass LUTFFGlobal
flyclass FFSetReset
flyclass FFClock
flyclass FFEnable
flyclass GlobalNetwork
flyclass NotConnected
method .create ( <various> o -- o )
method .optionCount ( o -- n )
method .optionWire ( i o -- wire )
method .getOption ( o -- n )
method .setOption ( n o -- )
method .print ( o -- )
method .getXY ( o -- x y )
method .getBit ( o -- b ) ( overloaded for wires and CramBits )
method .setBit ( b o -- )
method .inside ( x y o -- o' )
method .isLogic? ( o -- f )
method .isRam? ( o -- f )
method .isIO? ( o -- f )
method .isBottom? ( o -- f )
method .isInside? ( o -- f )
method .listBits ( x o -- )
method .enableBit ( o -- bit )
method .inputEnableBit ( o -- bit )
method .setNoResetBit ( o -- bit )
method .asyncResetBit ( o -- bit )
method .carryEnableBit ( o -- bit )
method .dffEnableBit ( o -- bit )
method .setPath ( n o -- )
method .getPath ( o -- n )
method .getInput ( n o -- wire )
method .setLogic ( n o -- )
method .getLogic ( o -- n )
method .routes ( xt target o -- ) ( xt gets: bit wire )
method .walk ( xt o -- ) ( xt gets: bit wire )
method .makeOutput ( o -- )
method .makeInput ( o -- )
method .setPinType ( n o -- )
method .getPinType ( o -- n )
method .getParity ( o -- n )
method .getRow ( o -- n )
initiate
CramBit implementation
0 cram-bank-width 2* 1- field x
0 cram-height 1- field y
m: .create ( x y o -- o ) put y put x ;m
m: .print { o -- } ." CramBit(" o x . ." , " o y . ." ) " ;m
m: .setBit { b o -- } b o x o y cram! ;m
m: .getBit { o -- b } o x o y cram@ ;m
: Sp4RVB { x y i -- o } x 1+ y i Sp4VB .create ;
: span4_horz { i o -- wire } o .getXY i Sp4HR .create ;
: span4_vert { i o -- wire }
o .isBottom? if
o .getXY 1+ i Sp4VB .create
else
i 35 > if NotConnected .create exit then
o .getXY i Sp4VB .create
then ;
: span12_vert { i o -- wire }
o .isBottom? if
o .getXY 1+ i Sp12VB .create
else
i 21 > if NotConnected .create exit then
o .getXY i Sp12VB .create
then ;
CramCell implementation
-13 cells-width 13 + 1- field cx
-13 cells-height 13 + 1- field cy
m: .create ( x y o -- o ) put cy put cx ;m
m: .print { o -- } ." CramCell(" o cx . ." , " o cy . ." ) " ;m
m: .getXY { o -- cx cy } o cx o cy ;m
m: .inside { x y o -- o' } o cx 54 * x +
o cx 6 > if logicram-diff - then
o cx 19 > if logicram-diff - then
o cy 16 * y + CramBit .create ;m
m: .isInside? { o -- f } o cx 0 >= o cx cells-width < and
o cy 0 >= o cy cells-height < and and ;m
m: .isIO? { o -- f } o cx 0 = o cx cells-width 1- = or
o cy 0 = or o cy cells-height 1- = or ;m
m: .isBottom? { o -- g } o cy 0= ;m
m: .isRam? { o -- f } o cx bram-column1 = o cx bram-column2 = or o .isIO? 0= and ;m
m: .isLogic? { o -- f } o .isRam? 0= o .isIO? 0= and ;m
: route12 { x y i m n target xt o }
target i o span12_vert = if
x y o .inside o .getXY m n IOInput .create xt execute
then ;
: route4v { x y i m n target xt o }
target i o span4_vert = if
x y o .inside o .getXY m n IOInput .create xt execute
then ;
: route4h { x y i m n target xt o }
target i o span4_horz = if
x y o .inside o .getXY m n IOInput .create xt execute
then ;
m: .routes { xt target o -- }
o .isIO? if
5 1 0 0 0 target xt o route12
5 3 8 0 0 target xt o route12
5 5 16 0 0 target xt o route12
23 0 16 0 0 target xt o route4v
23 1 0 0 0 target xt o route4v
23 2 40 0 0 target xt o route4v
23 3 4 0 0 target xt o route4h
25 0 24 0 0 target xt o route4v
25 1 8 0 0 target xt o route4v
25 2 0 0 0 target xt o route4h
25 3 8 0 0 target xt o route4h
26 1 32 0 0 target xt o route4v
26 2 12 0 0 target xt o route4h
4 6 2 0 1 target xt o route12
5 6 10 0 1 target xt o route12
4 7 18 0 1 target xt o route12
23 4 18 0 1 target xt o route4v
23 5 2 0 1 target xt o route4v
23 6 42 0 1 target xt o route4v
23 7 5 0 1 target xt o route4h
25 4 26 0 1 target xt o route4v
25 5 10 0 1 target xt o route4v
25 6 1 0 1 target xt o route4h
25 7 9 0 1 target xt o route4h
26 5 34 0 1 target xt o route4v
26 6 13 0 1 target xt o route4h
4 9 4 1 0 target xt o route12
5 9 12 1 0 target xt o route12
4 8 20 1 0 target xt o route12
23 8 20 1 0 target xt o route4v
23 9 4 1 0 target xt o route4v
23 10 44 1 0 target xt o route4v
23 11 6 1 0 target xt o route4h
25 8 28 1 0 target xt o route4v
25 9 12 1 0 target xt o route4v
25 10 2 1 0 target xt o route4h
25 11 10 1 0 target xt o route4h
26 9 36 1 0 target xt o route4v
26 10 14 1 0 target xt o route4h
5 10 6 1 1 target xt o route12
5 12 14 1 1 target xt o route12
5 14 22 1 1 target xt o route12
23 12 22 1 1 target xt o route4v
23 13 6 1 1 target xt o route4v
23 14 46 1 1 target xt o route4v
23 15 7 1 1 target xt o route4h
25 12 30 1 1 target xt o route4v
25 13 14 1 1 target xt o route4v
25 14 3 1 1 target xt o route4h
25 15 11 1 1 target xt o route4h
26 13 38 1 1 target xt o route4v
26 13 15 1 1 target xt o route4h
exit
then
o .isInside? 0= if exit then
8 0 do
target o .getXY i 2* Sp4HR .create = if
46 i 2* 1+ o .inside o .getXY i Output .create xt execute
then
target o .getXY i 2* 16 + Sp4HR .create = if
46 i 2* o .inside o .getXY i Output .create xt execute
then
target o .getXY i 2* 32 + Sp4HR .create = if
47 i 2* 1+ o .inside o .getXY i Output .create xt execute
then
target o .getXY i 2* 1+ Sp4RVB = if
52 i 2* 1+ o .inside o .getXY i Output .create xt execute
then
target o .getXY i 2* 17 + Sp4RVB = if
53 i 2* o .inside o .getXY i Output .create xt execute
then
target o .getXY i 2* 33 + Sp4RVB = if
53 i 2* 1+ o .inside o .getXY i Output .create xt execute
then
loop
4 0 do
target o .getXY i 2* 8 + Sp12HR .create = if
47 i 2* o .inside o .getXY i Output .create xt execute
then
target o .getXY i 2* Sp12HR .create = if
47 i 2* 8 + o .inside o .getXY i 4 + Output .create xt execute
then
target o .getXY i 2* Sp4VB .create = if
48 i 2* o .inside o .getXY i Output .create xt execute
then
target o .getXY i 2* 16 + Sp4VB .create = if
48 i 2* 1+ o .inside o .getXY i Output .create xt execute
then
target o .getXY i 2* 16 + Sp12HR .create = if
48 i 2* 8 + o .inside o .getXY i 4 + Output .create xt execute
then
target o .getXY i 2* 8 + Sp4VB .create = if
48 i 2* 1+ 8 + o .inside o .getXY i 4 + Output .create xt execute
then
target o .getXY i 2* Sp12VB .create = if
51 i 2* o .inside o .getXY i Output .create xt execute
then
target o .getXY i 2* 32 + Sp4VB .create = if
51 i 2* 1+ o .inside o .getXY i Output .create xt execute
then
target o .getXY i 2* 40 + Sp4VB .create = if
51 i 2* 8 + o .inside o .getXY i 4 + Output .create xt execute
then
target o .getXY i 2* 24 + Sp4VB .create = if
51 i 2* 1+ 8 + o .inside o .getXY i 4 + Output .create xt execute
then
target o .getXY i 2* 16 + Sp12VB .create = if
52 i 2* o .inside o .getXY i Output .create xt execute
then
target o .getXY i 2* 8 + Sp4VB .create = if
52 i 2* 8 + o .inside o .getXY i 4 + Output .create xt execute
then
loop
;m
: getBits { n i w -- n i } n w .getBit 1 and i lshift or i 1+ ;
: setBits { n w -- n } n 1 and w .setBit n 2/ ;
Output implementation CramCell extension
0 7 field bit
m: .create { cx cy b o -- o } cx cy o CramCell :: .create b swap put bit ;m
m: .print { o -- } ." Output(" o .getXY swap . . ." , " o bit . ." ) " ;m
m: .getBit ( o -- b ) bit ;m
m: .optionCount { o -- n } 0 ;m
m: .optionWire ( i o -- wire ) abort ;m
m: .setOption ( n o -- ) abort ;m
m: .getOption { o -- n } 0 ;m
create input_table Input0 , Input1 , Input2 , Input3 ,
m: .getInput { n o -- wire } o .getXY o .getBit n cells input_table + @ .create ;m
create logic_table $04 c, $14 c, $15 c, $05 c, $06 c, $16 c, $17 c, $07 c,
$03 c, $13 c, $12 c, $02 c, $01 c, $11 c, $10 c, $00 c,
m: .setLogic { n o -- } n ['] setBits o .listBits drop ;m
m: .getLogic { o -- n } 0 0 ['] getBits o .listBits drop ;m
m: .listBits { x o -- } 16 0 do
i logic_table + c@ 16 /mod >r 36 + r> o .getBit 2* + o .inside x execute
loop ;m
m: .setNoResetBit { o -- bit } 44 o .getBit 2* 1+ o .inside ;m
m: .asyncResetBit { o -- bit } 45 o .getBit 2* 1+ o .inside ;m
m: .carryEnableBit { o -- bit } 44 o .getBit 2* o .inside ;m
m: .dffEnableBit { o -- bit } 45 o .getBit 2* o .inside ;m
Input implementation Output extension
m: .getPath { o -- n } 0 0 ['] getBits o .listBits drop ;m
m: .setPath { n o -- } n ['] setBits o .listBits drop ;m
m: .optionCount { o -- n } 17 ;m
m: .getOption { o -- n } o .enableBit .getBit if
o .getPath 1+
else
0
then ;m
m: .setOption { n o -- } n if
-1 o .enableBit .setBit
n 1- o .setPath
else
0 o .enableBit .setBit
0 o .setPath ( for good measure )
then ;m
: inOptWire { i o lo hi -- wire }
i 0= if NotConnected .create exit then
i 1- 2 rshift 3 and { rt }
o .getXY
o .getBit 1 and if hi else lo then rt rshift 1 and i 1- 2* or
LocalG .create
;
Input0 implementation Input extension
m: .print { o -- } ." Input0(" o .getXY swap . . ." , " o .getBit . ." ) " ;m
m: .enableBit { o -- wire } 29 o .getBit 2* 1+ o .inside ;m
m: .listBits { x o -- } 26 o .getBit 2* 1+ o .inside x execute
26 o .getBit 2* o .inside x execute
27 o .getBit 2* 1+ o .inside x execute
28 o .getBit 2* 1+ o .inside x execute ;m
m: .optionWire ( i o -- wire ) $a $5 inOptWire ;m
Input1 implementation Input extension
m: .print { o -- } ." Input1(" o .getXY swap . . ." , " o .getBit . ." ) " ;m
m: .enableBit { o -- wire } 29 o .getBit 2* o .inside ;m
m: .listBits { x o -- } 30 o .getBit 2* 1+ o .inside x execute
30 o .getBit 2* o .inside x execute
27 o .getBit 2* o .inside x execute
28 o .getBit 2* o .inside x execute ;m
m: .optionWire ( i o -- wire ) $5 $a inOptWire ;m
Input2 implementation Input extension
m: .print { o -- } ." Input2(" o .getXY swap . . ." , " o .getBit . ." ) " ;m
m: .enableBit { o -- wire } 32 o .getBit 2* 1+ o .inside ;m
m: .listBits { x o -- } 35 o .getBit 2* 1+ o .inside x execute
35 o .getBit 2* o .inside x execute
34 o .getBit 2* 1+ o .inside x execute
33 o .getBit 2* 1+ o .inside x execute ;m
m: .optionWire ( i o -- wire ) $a $5 inOptWire ;m
Input3 implementation Input extension
m: .print { o -- } ." Input3(" o .getXY swap . . ." , " o .getBit . ." ) " ;m
m: .enableBit { o -- wire } 32 o .getBit 2* o .inside ;m
m: .listBits { x o -- } 31 o .getBit 2* 1+ o .inside x execute
31 o .getBit 2* o .inside x execute
34 o .getBit 2* o .inside x execute
33 o .getBit 2* o .inside x execute ;m
m: .optionWire ( i o -- wire ) $5 $a inOptWire ;m
LocalG implementation CramCell extension
0 31 field identifier
create localg_table LocalG0 , LocalG1 , LocalG2 , LocalG3 ,
m: .create { cx cy id o -- o }
id 4 mod cells localg_table + @ to o
cx cy o CramCell :: .create id swap put identifier ;m
m: .print { o -- } ." LocalG(" o .getXY swap . . ." , g" o identifier 8 /mod . . ." ) " ;m
m: .getPath { o -- n } 0 0 ['] getBits o .listBits drop ;m
m: .setPath { n o -- } n ['] setBits o .listBits drop ;m
m: .optionCount { o -- n } 15 ;m
m: .getBit { o -- n } o identifier 4 / 8 mod ;m
m: .getOption { o -- n } o .enableBit .getBit if
o .getPath 1-
else
0
then ;m
m: .setOption { n o -- } n if
-1 o .enableBit .setBit
n 1+ o .setPath
else
0 o .enableBit .setBit
0 o .setPath ( for good measure )
then ;m
: sp4skew { id off -- n } id 8 mod id 16 >= if 24 + then off + ;
: sp12skew { id off -- n cls } id 8 mod off + id 16 >= if Sp12VB else Sp12HR then ;
m: .optionWire { i o -- wire }
i 0 >= assert i o .optionCount < assert
i 0= if NotConnected .create exit then
i case
( TODO: shift by 2 and add r_v_b )
6 of o .getXY o identifier 0 sp12skew .create exit endof
7 of o .getXY o identifier 8 sp12skew .create exit endof
8 of o .getXY o identifier 16 sp12skew .create exit endof
9 of o .getXY o identifier 16 sp4skew Sp4VB .create exit endof
10 of o .getXY o identifier 0 sp4skew Sp4HR .create exit endof
11 of o .getXY o identifier 0 sp4skew Sp4VB .create exit endof
12 of o .getXY o identifier 8 sp4skew Sp4VB .create exit endof
13 of o .getXY o identifier 8 sp4skew Sp4HR .create exit endof
14 of o .getXY o identifier 16 sp4skew Sp4HR .create exit endof
endcase
o identifier 16 < if
i case
1 of 0 -1 endof
2 of 0 1 endof
3 of 0 0 endof
4 of 1 -1 endof
5 of -1 0 endof
endcase
else
i case
1 of 1 1 endof
2 of -1 1 endof
3 of 0 0 endof
4 of -1 -1 endof
5 of 1 0 endof
endcase
then
{ x y }
o .getXY y + to y x + to x
x 1 < if NotConnected .create exit then
x cells-width 1- >= if NotConnected .create exit then
y cells-height >= if NotConnected .create exit then
y 0< if NotConnected .create exit then
x y o identifier 8 mod Output .create
;m
LocalG0 implementation LocalG extension
m: .enableBit { o -- wire } 17 o .getBit 2* 1+ o .inside ;m
m: .listBits { x o -- } 14 o .getBit 2* 1+ o .inside x execute
15 o .getBit 2* 1+ o .inside x execute
14 o .getBit 2* o .inside x execute
16 o .getBit 2* 1+ o .inside x execute ;m
LocalG1 implementation LocalG extension
m: .enableBit { o -- wire } 17 o .getBit 2* o .inside ;m
m: .listBits { x o -- } 18 o .getBit 2* 1+ o .inside x execute
15 o .getBit 2* o .inside x execute
18 o .getBit 2* o .inside x execute
16 o .getBit 2* o .inside x execute ;m
LocalG2 implementation LocalG extension
m: .enableBit { o -- wire } 22 o .getBit 2* 1+ o .inside ;m
m: .listBits { x o -- } 25 o .getBit 2* 1+ o .inside x execute
24 o .getBit 2* 1+ o .inside x execute
25 o .getBit 2* o .inside x execute
23 o .getBit 2* 1+ o .inside x execute ;m
LocalG3 implementation LocalG extension
m: .enableBit { o -- wire } 22 o .getBit 2* o .inside ;m
m: .listBits { x o -- } 21 o .getBit 2* 1+ o .inside x execute
24 o .getBit 2* o .inside x execute
21 o .getBit 2* o .inside x execute
23 o .getBit 2* o .inside x execute ;m
create iopermy 0 , 1 , 3 , 2 , 4 , 5 , 7 , 6 , 8 , 9 , 11 , 10 , 12 , 13 , 15 , 14 ,
: >iopermy ( n -- n ) cells iopermy + @ ;
IOLocalG implementation CramCell extension
0 15 field identifier
create localg_table IOLocalG0 , IOLocalG1 ,
m: .create { cx cy id o -- o }
id 2 mod cells localg_table + @ to o
cx cy o CramCell :: .create id swap put identifier ;m
m: .print { o -- } ." IOLocalG(" o .getXY swap . . ." , g" o identifier 8 /mod . . ." ) " ;m
m: .inside { x y o -- wire } x y >iopermy o .isBottom? if 15 swap - then o CramCell :: .inside ;m
m: .getPath { o -- n } 0 0 ['] getBits o .listBits drop ;m
m: .setPath { n o -- } n ['] setBits o .listBits drop ;m
m: .optionCount { o -- n } 15 ;m
m: .getBit { o -- n } o identifier 8 mod ;m
m: .getRow { o -- n } o identifier 2/ ;m
m: .getOption { o -- n } o .enableBit .getBit if
o .getPath 1-
else
0
then ;m
m: .setOption { n o -- } n if
-1 o .enableBit .setBit
n 1+ o .setPath
else
0 o .enableBit .setBit
0 o .setPath ( for good measure )
then ;m
: iosp4v { offset o -- wire } o .getBit offset + o span4_vert ;
: iosp12v { offset o -- wire } o .getBit offset + o span12_vert ;
: iosp4h { offset o -- wire } o .getBit offset + o span4_horz ;
m: .optionWire { i o -- wire }
i 0 >= assert i o .optionCount < assert
i 0= if NotConnected .create exit then
1 +to i ( There's no 1 )
i case
5 of 0 o iosp4h exit endof
6 of 8 o iosp4h exit endof
7 of 0 o iosp12v exit endof
8 of 8 o iosp12v exit endof
9 of 16 o iosp12v exit endof
10 of 0 o iosp4v exit endof
11 of 8 o iosp4v exit endof
12 of 16 o iosp4v exit endof
13 of 24 o iosp4v exit endof
14 of 32 o iosp4v exit endof
15 of 40 o iosp4v exit endof
endcase
i 3 - 1 o .getXY nip if negate then { x y }
o .getXY y + to y x + to x
( Could use .isLogic ? )
x 1 < if NotConnected .create exit then
x cells-width 1- >= if NotConnected .create exit then
y cells-height 1- >= if NotConnected .create exit then
y 1 < if NotConnected .create exit then
x y o .getBit Output .create
;m
IOLocalG0 implementation IOLocalG extension
m: .enableBit { o -- wire } 19 o .getRow 2* 1+ o .inside ;m
m: .listBits { x o -- } 16 o .getRow 2* 1+ o .inside x execute
16 o .getRow 2* o .inside x execute
17 o .getRow 2* 1+ o .inside x execute
18 o .getRow 2* 1+ o .inside x execute ;m
IOLocalG1 implementation IOLocalG extension
m: .enableBit { o -- wire } 19 o .getRow 2* o .inside ;m
m: .listBits { x o -- } 20 o .getRow 2* 1+ o .inside x execute
20 o .getRow 2* o .inside x execute
17 o .getRow 2* o .inside x execute
18 o .getRow 2* o .inside x execute ;m
: optcount { n bit wire -- n } n 1+ ;
: optget { goal n bit wire -- goal n } bit .getBit if n else goal then n 1+ ;
: optset { goal n bit wire -- goal n } goal n = bit .setBit goal n 1+ ;
: optwire { answer goal n bit wire -- answer goal n } n goal = if wire else answer then goal n 1+ ;
: cross { idx n -- off ii } idx n /mod swap over 1 and xor ;
SpanWire implementation CramCell extension
m: .optionCount { o -- n } 1 ['] optcount o .walk ;m
m: .getOption { o -- n } 0 1 ['] optget o .walk drop ;m
m: .setOption { n o -- } n 1 ['] optset o .walk 2drop ;m
m: .optionWire { i o -- wire } NotConnected .create i 1 ['] optwire o .walk 2drop ;m
Sp4HR implementation SpanWire extension
0 11 field index
m: .create { cx cy idx o -- o } cx idx 12 cross { ii } - cy o SpanWire :: .create
ii swap put index ;m
m: .print { o -- } ." Sp4HR(" o .getXY swap . . ." , " o index . ." ) " ;m
m: .walk { xt o -- } 6 -5 do xt o o .getXY swap i + swap CramCell .create .routes loop ;m
Sp4VB implementation SpanWire extension
0 11 field index
m: .create { cx cy idx o -- o } cx cy idx 12 cross { ii } + o SpanWire :: .create
ii swap put index ;m
m: .print { o -- } ." Sp4VB(" o .getXY swap . . ." , " o index . ." ) " ;m
m: .walk { xt o -- } 6 -5 do xt o o .getXY i + CramCell .create .routes loop ;m
Sp12HR implementation SpanWire extension
0 1 field index
m: .create { cx cy idx o -- o } cx idx 2 cross { ii } - cy o SpanWire :: .create
ii swap put index ;m
m: .print { o -- } ." Sp12HR(" o .getXY swap . . ." , " o index . ." ) " ;m
m: .walk { xt o -- } 13 -13 do xt o o .getXY swap i + swap CramCell .create .routes loop ;m
Sp12VB implementation SpanWire extension
0 1 field index
m: .create { cx cy idx o -- o } cx cy idx 2 cross { ii } + o SpanWire :: .create
ii swap put index ;m
m: .print { o -- } ." Sp12VB(" o .getXY swap . . ." , " o index . ." ) " ;m
m: .walk { xt o -- } 13 -13 do xt o o .getXY i + CramCell .create .routes loop ;m
IOPin implementation CramCell extension
0 1 field pinIndex
m: .create { x y pin o -- o } x y o CramCell :: .create pin swap put pinIndex ;m
m: .print { o -- } ." IOPin(" o .getXY swap . . o pinIndex . ." ) " ;m
m: .inside { x y o -- wire } o .getXY nip 0= if 15 y - to y then x y o CramCell :: .inside ;m
: nopullup { o -- }
o pinIndex 0= if
-1 37 7 o .inside .setBit
else
-1 37 12 o .inside .setBit
then
;
m: .makeInput { o -- }
1 o .setPinType
-1 o .enableBit .setBit
-1 o .inputEnableBit .setBit
o nopullup
(
o .getXY o pinIndex 0 IOInput .create
)
o .getXY o pinIndex 2* Output .create
;m
m: .makeOutput { o -- output }
25 o .setPinType
-1 o .enableBit .setBit
0 o .inputEnableBit .setBit
o nopullup
o .getXY o pinIndex IOOutput0 .create
;m
m: .getPinType { o -- n } 0 0 ['] getBits o .listBits drop ;m
m: .setPinType { n o -- } n ['] setBits o .listBits drop ;m
m: .listBits { x o -- ... }
5 2 o pinIndex 11 * + o .inside x execute
4 2 o pinIndex 11 * + o .inside x execute
5 0 o pinIndex 11 * + o .inside x execute
4 0 o pinIndex 11 * + o .inside x execute
4 4 o pinIndex 11 * + o .inside x execute
5 4 o pinIndex 11 * + o .inside x execute
;m
m: .enableBit { o -- bit } o pinIndex if 27 1 else 26 7 then o .inside ;m
m: .inputEnableBit { o -- bit } 27 9 o pinIndex 1 xor 2* - o .inside ;m
: ioOptWire { i o parity -- wire }
o .getXY i 2* parity xor i 4 >= if 1 xor then IOLocalG .create
;
IOInput implementation SpanWire extension
0 1 field pinIndex
0 1 field dinNum
m: .create { x y pin din o -- o } x y o CramCell :: .create pin swap put pinIndex din swap put dinNum ;m
m: .print { o -- } ." IOInput(" o .getXY swap . . o pinIndex . o dinNum . ." ) " ;m
m: .optionCount { o -- n } 0 ;m
m: .getOption { o -- n } 0 ;m
IOOutput implementation CramCell extension
0 1 field pinIndex
m: .create { x y pin o -- o } x y o CramCell :: .create pin swap put pinIndex ;m
m: .print { o -- } ." IOOutput(" o .getXY swap . . o pinIndex . ." ) " ;m
m: .inside { x y o -- wire } x y o .isBottom? if 15 swap - then o CramCell :: .inside ;m
m: .getPath { o -- n } 0 0 ['] getBits o .listBits drop ;m
m: .setPath { n o -- } n ['] setBits o .listBits drop ;m
m: .optionCount { o -- n } 9 ;m
m: .getOption { o -- n } o .enableBit .getBit if
o .getPath 1+
else
0
then ;m
m: .setOption { n o -- } n if
-1 o .enableBit .setBit
n 1- o .setPath
else
0 o .enableBit .setBit
0 o .setPath ( for good measure )
then ;m
m: .optionWire { i o -- wire }
i 0= if NotConnected .create exit then
i 1- o o pinIndex o .getParity xor ioOptWire ;m
IOOutput0 implementation IOOutput extension
m: .print { o -- } ." IOOutput0(" o .getXY swap . . o pinIndex . ." ) " ;m
m: .enableBit { o -- wire } 35 5 o pinIndex 5 * + o .inside ;m
m: .listBits { x o -- ... }
34 5 o pinIndex 5 * + o .inside x execute
35 4 o pinIndex 7 * + o .inside x execute
34 4 o pinIndex 7 * + o .inside x execute
;m
m: .getParity { o -- n } 0 ;m
IOOutput1 implementation IOOutput extension
m: .print { o -- } ." IOOutput1(" o .getXY swap . . o pinIndex . ." ) " ;m
m: .enableBit { o -- wire } 33 9 o .inside ;m
m: .listBits { x o -- ... }
32 9 o pinIndex 5 * + o .inside x execute
32 8 o pinIndex 7 * + o .inside x execute
33 8 o pinIndex 7 * + o .inside x execute
;m
m: .getParity { o -- n } 1 ;m
IOEnable implementation IOOutput extension
m: .print { o -- } ." IOEnable(" o .getXY swap . . o pinIndex . ." ) " ;m
m: .enableBit { o -- wire } 33 5 o .inside ;m
m: .listBits { x o -- ... }
32 5 o pinIndex 5 * + o .inside x execute
32 4 o pinIndex 7 * + o .inside x execute
33 4 o pinIndex 7 * + o .inside x execute
;m
m: .getParity { o -- n } 1 ;m
IOFabOutput implementation IOOutput extension
m: .create { x y o -- o } x y 0 o IOOutput :: .create ;m
m: .print { o -- } ." IOFabOutput(" o .getXY swap . . ." ) " ;m
m: .enableBit { o -- wire } 37 4 o .inside ;m
m: .listBits { x o -- ... }
37 5 o .inside x execute
36 4 o .inside x execute
36 5 o .inside x execute
;m
m: .getParity { o -- n } 0 ;m
LUTFFGlobal implementation CramCell extension
m: .print { o -- } ." LUTFFGlobal(" o .getXY swap . . ." ) " ;m
m: .getPath { o -- n } 0 0 ['] getBits o .listBits drop ;m
m: .setPath { n o -- } n ['] setBits o .listBits drop ;m
m: .optionCount { o -- n } 9 ;m
m: .getOption { o -- n } o .enableBit .getBit if
o .getPath 1+
else
0
then ;m
m: .setOption { n o -- } n if
-1 o .enableBit .setBit
n 1- o .setPath
else
0 o .enableBit .setBit
0 o .setPath ( for good measure )
then ;m
m: .optionWire { i o -- wire }
o .getXY i case
( TODO: glb_netwk )
5 of 0 o .getRow + LocalG .create exit endof
6 of 9 o .getRow + LocalG .create exit endof
7 of 16 o .getRow + LocalG .create exit endof
8 of 25 o .getRow + LocalG .create exit endof
endcase 2drop NotConnected .create ;m
FFSetReset implementation LUTFFGlobal extension
m: .print { o -- } ." FFSetReset(" o .getXY swap . . ." ) " ;m
m: .enableBit { o -- wire } 1 14 o .inside ;m
m: .listBits { x o -- ... }
0 15 o .inside x execute
0 14 o .inside x execute
1 15 o .inside x execute
;m
m: .getRow ( -- n ) 4 ;m
m: .optionWire { i o -- wire }
i 0 > i 5 < and if i 1- 2* GlobalNetwork .create exit then
i o LUTFFGlobal :: .optionWire ;m
FFEnable implementation LUTFFGlobal extension
m: .print { o -- } ." FFEnable(" o .getXY swap . . ." ) " ;m
m: .enableBit { o -- wire } 1 4 o .inside ;m
m: .listBits { x o -- ... }
0 5 o .inside x execute
0 4 o .inside x execute
1 5 o .inside x execute
;m
m: .getRow ( -- n ) 2 ;m
m: .optionWire { i o -- wire }
i 0 > i 5 < and if i 1- 2* 1+ GlobalNetwork .create exit then
i o LUTFFGlobal :: .optionWire ;m
FFClock implementation LUTFFGlobal extension
m: .print { o -- } ." FFClock(" o .getXY swap . . ." ) " ;m
m: .enableBit { o -- wire } 2 2 o .inside ;m
m: .optionCount { o -- n } 13 ;m
m: .listBits { x o -- ... }
0 3 o .inside x execute
1 2 o .inside x execute
0 2 o .inside x execute
2 1 o .inside x execute
;m
m: .optionWire { i o -- wire }
i 0 > i 9 < and if i 1- GlobalNetwork .create exit then
i 4 - o LUTFFGlobal :: .optionWire ;m
GlobalNetwork implementation
0 7 field index
m: .create { i o -- o } i o put index ;m
m: .print { o -- } ." GlobalNetwork(" o index . ." ) " ;m
m: .getOption { o -- n } 0 ;m
m: .optionCount { o -- n } 0 ;m
NotConnected implementation
m: .create ( o -- o ) ;m
m: .print { o -- } ." NotConnected" ;m
m: .getOption { o -- n } 0 ;m
m: .optionCount { o -- n } 0 ;m
: pin ( n -- o ) pin#s IOPin .create ;
: route { src dst -- f }
\ ." SRC: " src .print ." DST: " dst .print cr
src dst = if -1 exit then
dst .getOption { p }
p if src p dst .optionWire recurse exit then
dst .optionCount { n }
n 0 ?do
i dst .setOption
src i dst .optionWire recurse if -1 unloop exit then
0 dst .setOption
loop 0
;
: route. { src dst }
." ROUTE: "
begin src dst <> while
dst .print ." <- "
dst .getOption dst .optionWire to dst
repeat
src .print cr
;
previous
forth definitions

View File

@ -0,0 +1,203 @@
\ Copyright 2025 Bradley D. Nelson
\
\ Licensed under the Apache License, Version 2.0 (the "License");
\ you may not use this file except in compliance with the License.
\ You may obtain a copy of the License at
\
\ http://www.apache.org/licenses/LICENSE-2.0
\
\ Unless required by applicable law or agreed to in writing, software
\ distributed under the License is distributed on an "AS IS" BASIS,
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\ See the License for the specific language governing permissions and
\ limitations under the License.
needs ice40_config.fs
ice40 definitions
vocabulary storage storage definitions
: ew! ( n a -- ) over 8 rshift over c! 1+ c! ;
: w, ( n -- ) here ew! 2 allot ;
create header1
$ff c, $00 c, $00 c, $ff c, ( Init blop, maybe not needed? )
$7e c, $aa c, $99 c, $7e c, ( Preamble )
$51 c, $00 c, ( Frequency 0=low, 1=medium, 2=high )
$01 c, $05 c, ( Reset CRC crc = 0xffff )
here header1 - constant header1#
create header2
$92 c, $0020 w, ( Set flags bit0=nosleep bit5=warmboot )
$62 c, cram-bank-width 1- w, ( Set bank width )
$82 c, $0000 w, ( Set bank offset to 0 )
here header2 - constant header2#
0 value bank-id
0 value bank-height
create bank-header
$72 c, here to bank-height 0 w, ( Set bank height, 5k only, upper vs lower )
$11 c, here to bank-id 0 c, ( Set bank )
$01 c, $01 c, ( Prefix )
here bank-header - constant bank-header#
create bank-footer
$00 c, $00 c, ( Suffix )
here bank-footer - constant bank-footer#
create header3
$72 c, bram-chunk-size w, ( Setting bank height? )
here header3 - constant header3#
0 value bram-bank
create bram-header1
$11 c, here to bram-bank 0 c, ( Setting bank )
here bram-header1 - constant bram-header1#
0 value bram-offset
0 value bram-bank-width
create bram-header2
$82 c, here to bram-offset 0 w, ( Setting bank offset )
$62 c, here to bram-bank-width 0 w, ( Setting bank width )
here bram-header2 - constant bram-header2#
0 value footer-crc
create footer
$22 c, here to footer-crc $0000 w, ( CRC )
$01 c, $06 c, ( Wakeup )
$00 c, ( Padding )
here footer - constant footer#
variable crc16
: +crc16 ( ch -- )
7 for
dup i rshift 1 and ( peel off one bit )
crc16 uw@ 15 rshift xor if $1021 else 0 then
crc16 uw@ 2* xor crc16 w!
next
drop
;
: *crc16 ( a n -- ) for aft dup c@ +crc16 1+ then next drop ;
: crc-write ( a n output -- ) >r 2dup *crc16 r> execute ;
: cram-write { output -- }
( write header )
header1 header1# output execute
$ffff crc16 w!
header2 header2# output crc-write
( Bank 0 )
0 bank-id c!
cram-height-lower bank-height ew!
bank-header bank-header# output crc-write
cram cram-bank-width cram-height-lower * 8 / output crc-write
bank-footer bank-footer# output crc-write
( Bank 1 )
1 bank-id c!
cram-height-upper bank-height ew!
bank-header bank-header# output crc-write
cram cram-bank-width cram-height-lower * 8 / +
cram-bank-width cram-height-upper * 8 / output crc-write
bank-footer bank-footer# output crc-write
( Bank 2 )
2 bank-id c!
cram-height-lower bank-height ew!
bank-header bank-header# output crc-write
cram cram-bank-width cram-height-lower cram-height-upper + * 8 / +
cram-bank-width cram-height-lower * 8 / output crc-write
bank-footer bank-footer# output crc-write
( Bank 3 )
3 bank-id c!
cram-height-upper bank-height ew!
bank-header bank-header# output crc-write
cram cram-bank-width cram-height-lower 2* cram-height-upper + * 8 / +
cram-bank-width cram-height-upper * 8 / output crc-write
bank-footer bank-footer# output crc-write
( BRAM Header )
header3 header3# output crc-write
( BRAM Bank 0 )
0 bram-bank c!
bram-header1 bram-header1# output crc-write
bram-chunk-size 0 * bram-offset ew!
bram-width-lower 1- bram-bank-width ew!
bram-header2 bram-header2# output crc-write
bram-chunk-size 1 * bram-offset ew!
bram-width-lower 1- bram-bank-width ew!
bram-header2 bram-header2# output crc-write
( BRAM Bank 1 )
1 bram-bank c!
bram-header1 bram-header1# output crc-write
bram-chunk-size 0 * bram-offset ew!
bram-width-upper 1- bram-bank-width ew!
bram-header2 bram-header2# output crc-write
bram-chunk-size 1 * bram-offset ew!
bram-width-upper 1- bram-bank-width ew!
bram-header2 bram-header2# output crc-write
( BRAM Bank 2 )
2 bram-bank c!
bram-header1 bram-header1# output crc-write
bram-chunk-size 0 * bram-offset ew!
bram-width-lower 1- bram-bank-width ew!
bram-header2 bram-header2# output crc-write
bram-chunk-size 1 * bram-offset ew!
bram-width-lower 1- bram-bank-width ew!
bram-header2 bram-header2# output crc-write
( BRAM Bank 3 )
3 bram-bank c!
bram-header1 bram-header1# output crc-write
bram-chunk-size 0 * bram-offset ew!
bram-width-upper 1- bram-bank-width ew!
bram-header2 bram-header2# output crc-write
bram-chunk-size 1 * bram-offset ew!
bram-width-upper 1- bram-bank-width ew!
bram-header2 bram-header2# output crc-write
( write footer )
$22 +crc16 ( Add first byte of footer )
crc16 uw@ footer-crc ew! ( Update CRC )
footer footer# output crc-write
;
0 value save-fh
: save-write ( a n -- ) save-fh write-file throw ;
ice40 definitions also storage
: save ( a n -- )
w/o bin create-file throw to save-fh
['] save-write cram-write
save-fh close-file throw
;
DEFINED? ice [IF]
also ice
DEFINED? ice_cram_open [IF]
: deploy
ice_cram_open
['] ice_cram_write cram-write
ice_cram_close
;
[THEN]
previous
[THEN]
previous
forth definitions

View File

@ -0,0 +1,104 @@
\ Copyright 2025 Bradley D. Nelson
\
\ Licensed under the Apache License, Version 2.0 (the "License");
\ you may not use this file except in compliance with the License.
\ You may obtain a copy of the License at
\
\ http://www.apache.org/licenses/LICENSE-2.0
\
\ Unless required by applicable law or agreed to in writing, software
\ distributed under the License is distributed on an "AS IS" BASIS,
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\ See the License for the specific language governing permissions and
\ limitations under the License.
needs ice40_layout.fs
needs ice40_allocation.fs
ice40 synthesis definitions
39 constant LED_G
40 constant LED_B
41 constant LED_R
: XOR1 ( a b -- o ) NotConnected NotConnected $6666 LUT4 ;
: OR1 ( a b -- o ) NotConnected NotConnected $eeee LUT4 ;
: AND1 ( a b -- o ) NotConnected NotConnected $8888 LUT4 ;
: INVERT1 ( a b -- o ) NotConnected NotConnected NotConnected $5555 LUT4 ;
: BUFFER1 ( a b -- o ) NotConnected NotConnected NotConnected $aaaa LUT4 ;
: HA ( x y -- so co ) 2dup AND1 >r XOR1 r> ;
: FA ( x y z -- so co ) HA >r HA r> OR1 ;
: BUS ( v bus -- bus ) here >r , , r> ;
: UNBUS ( bus -- v bus ) dup cell+ @ swap @ ;
: nBUS ( v* n -- bus ) 0 swap 0 ?do BUS loop ;
: nUNBUS ( bus -- v* ) begin dup while UNBUS repeat drop ;
: NEARBY { wire -- wire } wire .getXY dup 2 < if 1+ else 1- then
2dup CramCell .create .isRam? if >r 1+ r> then
PLACE wire ;
: IN1PIN ( n -- bus ) pin .makeInput NEARBY BUFFER1 ;
: OUT1PIN! ( wire n -- ) pin .makeOutput NEARBY >r BUFFER1 r> route! ;
: INPINS ( p1..pn n -- wire ) 0 swap 0 ?do swap IN1PIN swap BUS loop ;
: OUTPINS! ( bus p1..pn n -- )
nBUS begin dup while
UNBUS >r swap UNBUS >r swap OUT1PIN! r> r>
repeat 2drop ;
: REVERSE ( a -- a' )
0 swap begin dup while
UNBUS >r swap BUS r>
repeat drop
;
: INVERT ( a -- a' )
dup 0= if exit then
UNBUS >r INVERT1 r> recurse BUS
;
: BUFFER ( a -- a' )
dup 0= if exit then
UNBUS >r BUFFER1 r> recurse BUS
;
: AND ( a b -- c )
dup 0= if nip exit then
UNBUS >r >r UNBUS r> swap >r AND1
r> r> recurse BUS
;
: OR ( a b -- c )
dup 0= if nip exit then
UNBUS >r >r UNBUS r> swap >r OR1
r> r> recurse BUS
;
: XOR ( a b -- c )
dup 0= if nip exit then
UNBUS >r >r UNBUS r> swap >r XOR1
r> r> recurse BUS
;
: +c ( a b ci -- c )
>r dup 0= if 2drop r> 0 BUS exit then r>
-rot
UNBUS >r >r UNBUS r> swap >r FA
r> r> rot recurse BUS
;
: + ( a b -- c ) NotConnected +c ;
: REGISTER ( n -- bus )
0 swap 0 ?do FFL swap BUS loop REVERSE ;
: REG! ( v a -- )
dup 0= if 2drop exit then
UNBUS >r >r UNBUS r> swap >r FF!
r> r> recurse
;
forth definitions