Initial commit
This commit is contained in:
commit
c322debb7b
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
result
|
||||
BUILD/
|
15
shell.nix
Normal file
15
shell.nix
Normal file
@ -0,0 +1,15 @@
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
let
|
||||
unstable = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/nixpkgs-unstable.tar.gz") { };
|
||||
in
|
||||
pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
unstable.silice
|
||||
|
||||
icestorm
|
||||
yosys
|
||||
nextpnr
|
||||
|
||||
dfu-util
|
||||
];
|
||||
}
|
58
syntax-example.si
Normal file
58
syntax-example.si
Normal file
@ -0,0 +1,58 @@
|
||||
$$Period = 1 / Frequency;
|
||||
$$NSPerClock = 1000000000 * Period;
|
||||
$$ClocksPerMS = math.floor( 1000000 / NSPerClock );
|
||||
|
||||
algorithm Debounce( input uint1 Source, output uint1 Dest ) <autorun> {
|
||||
uint24 Clocks = 0;
|
||||
uint8 Bitmap = 0;
|
||||
|
||||
while ( 1 ) {
|
||||
Clocks = Clocks + 1;
|
||||
|
||||
if ( Clocks == $ClocksPerMS$ ) {
|
||||
Bitmap = ( Bitmap << 1 ) | Source;
|
||||
Clocks = 0;
|
||||
}
|
||||
|
||||
// If all the bits are set then the button should have finished bouncing
|
||||
// and the output should be reliable.
|
||||
Dest = ( Bitmap == 8hff ) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
subroutine WaitForRisingEdge( input uint1 Signal, output uint1 Debug ) {
|
||||
uint1 Last = 0;
|
||||
|
||||
Debug = 1;
|
||||
|
||||
while ( 1 ) {
|
||||
if ( Last == 0 && Signal == 1 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
Last = Signal;
|
||||
}
|
||||
|
||||
Debug = 0;
|
||||
}
|
||||
|
||||
algorithm main( output uint$NUM_LEDS$ leds, output uint$NUM_GPIO_OUT$ gp, input uint$NUM_GPIO_IN$ gn ) {
|
||||
uint1 FilteredButton = 0;
|
||||
uint1 Button = 0;
|
||||
uint1 State = 0;
|
||||
|
||||
Debounce Btn(
|
||||
Source <: Button,
|
||||
Dest :> FilteredButton
|
||||
);
|
||||
|
||||
Button := gn[ 10,1 ];
|
||||
leds[ 0,1 ] := State;
|
||||
|
||||
while ( 1 ) {
|
||||
// Error
|
||||
// ^^^^^^^^^^^^^^^^^^^ incorrect input parameters in call to algorithm 'WaitForRisingEdge', last correct match was parameter 'Signal'
|
||||
( ) <- WaitForRisingEdge <- ( FilteredButton, LED );
|
||||
State = ~State;
|
||||
}
|
||||
}
|
10
test.si
Normal file
10
test.si
Normal file
@ -0,0 +1,10 @@
|
||||
unit main(output uint8 leds) {
|
||||
algorithm {
|
||||
uint8 table[8] = {0,1,2,3,4,5,6,7};
|
||||
uint8 n = 0;
|
||||
while (n != 8) {
|
||||
__display("[%d] = %d",n,table[n]);
|
||||
n = n + 1;
|
||||
}
|
||||
}
|
||||
}
|
363
wfc_basic.si
Normal file
363
wfc_basic.si
Normal file
@ -0,0 +1,363 @@
|
||||
// SL 2020-07-13
|
||||
// Wave function collapse / Model synthesis (with image output)
|
||||
// MIT license, see LICENSE_MIT in Silice repo root
|
||||
// https://github.com/sylefeb/Silice
|
||||
// @sylefeb 2020
|
||||
|
||||
$$if DE10NANO or SIMULATION then
|
||||
$$Nlog = 3
|
||||
$$else
|
||||
$$Nlog = 3
|
||||
$$end
|
||||
|
||||
$$N = (1<<Nlog)
|
||||
|
||||
$$if not SIMULATION then
|
||||
$$BUTTONS = 1
|
||||
$$end
|
||||
|
||||
$include('../vga_demo/vga_demo_main.si')
|
||||
|
||||
$$PROBLEM = 'problems/knots/'
|
||||
$$dofile('pre_rules.lua')
|
||||
|
||||
// -------------------------
|
||||
// rule-processor
|
||||
// applies the neighboring rules
|
||||
|
||||
algorithm wfc_rule_processor(
|
||||
input uint$L$ site,
|
||||
input uint$L$ left, // -1, 0
|
||||
input uint$L$ right, // 1, 0
|
||||
input uint$L$ top, // 0,-1
|
||||
input uint$L$ bottom, // 0, 1
|
||||
output! uint$L$ newsite,
|
||||
output! uint1 nstable
|
||||
) {
|
||||
always {
|
||||
newsite = site & (
|
||||
$$for i=1,L do
|
||||
({$L${right[$i-1$,1]}} & $L$b$Rleft[i]$)
|
||||
$$if i < L then
|
||||
|
|
||||
$$end
|
||||
$$end
|
||||
) & (
|
||||
$$for i=1,L do
|
||||
({$L${left[$i-1$,1]}} & $L$b$Rright[i]$)
|
||||
$$if i < L then
|
||||
|
|
||||
$$end
|
||||
$$end
|
||||
) & (
|
||||
$$for i=1,L do
|
||||
({$L${bottom[$i-1$,1]}} & $L$b$Rtop[i]$)
|
||||
$$if i < L then
|
||||
|
|
||||
$$end
|
||||
$$end
|
||||
) & (
|
||||
$$for i=1,L do
|
||||
({$L${top[$i-1$,1]}} & $L$b$Rbottom[i]$)
|
||||
$$if i < L then
|
||||
|
|
||||
$$end
|
||||
$$end
|
||||
)
|
||||
;
|
||||
nstable = (newsite != site);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// produce a vector of '1' for init with all labels
|
||||
|
||||
$$ones='' .. L .. 'b'
|
||||
$$for i=1,L do
|
||||
$$ ones = ones .. '1'
|
||||
$$end
|
||||
|
||||
// -------------------------
|
||||
// helper function to locate neighbors
|
||||
|
||||
$$function neighbors(i)
|
||||
$$ local x = i%N
|
||||
$$ local y = i//N
|
||||
$$ local xm1 = x-1
|
||||
$$ local xp1 = x+1
|
||||
$$ local ym1 = y-1
|
||||
$$ local yp1 = y+1
|
||||
$$ -- make toroidal if outside of grid
|
||||
$$ if xm1 < 0 then xm1 = N-1 end
|
||||
$$ if xp1 > N-1 then xp1 = 0 end
|
||||
$$ if ym1 < 0 then ym1 = N-1 end
|
||||
$$ if yp1 > N-1 then yp1 = 0 end
|
||||
$$ local l = xm1+y*N
|
||||
$$ local r = xp1+y*N
|
||||
$$ local t = x+ym1*N
|
||||
$$ local b = x+yp1*N
|
||||
$$ return l,r,t,b
|
||||
$$end
|
||||
|
||||
// -------------------------
|
||||
// algorithm to make a choice
|
||||
// this is akin to a reduction
|
||||
// - each bit proposes its rank
|
||||
// - when two are present, one is randomly selected
|
||||
algorithm makeAChoice(
|
||||
input uint$L$ i,
|
||||
input uint16 rand,
|
||||
output! uint$L$ o)
|
||||
{
|
||||
|
||||
$$L_pow2=0
|
||||
$$tmp = L
|
||||
$$while tmp > 1 do
|
||||
$$ L_pow2 = L_pow2 + 1
|
||||
$$ tmp = (tmp/2)
|
||||
$$end
|
||||
$$print('choice reducer has ' .. L_pow2 .. ' levels')
|
||||
|
||||
$$nr = 0
|
||||
$$for lvl=L_pow2-1,0,-1 do
|
||||
$$ for i=0,(1<<lvl)-1 do
|
||||
uint5 keep_$lvl$_$2*i$_$2*i+1$ :=
|
||||
$$ if lvl == L_pow2-1 then
|
||||
$$ if 2*i < L then
|
||||
$$ if 2*i+1 < L then
|
||||
(i[$2*i$,1] && i[$2*i+1$,1]) ? (rand[$nr$,1] ? $2*i$ : $2*i+1$) : (i[$2*i$,1] ? $2*i$ : (i[$2*i+1$,1] ? $2*i+1$ : 0)) ;
|
||||
$$ else
|
||||
(i[$2*i$,1] ? $2*i$ : 0) ;
|
||||
$$ end
|
||||
$$ else
|
||||
0;
|
||||
$$ end
|
||||
$$ else
|
||||
(keep_$lvl+1$_$4*i$_$4*i+1$ && keep_$lvl+1$_$4*i+2$_$4*i+3$) ? (rand[$nr$,1] ? keep_$lvl+1$_$4*i$_$4*i+1$ : keep_$lvl+1$_$4*i+2$_$4*i+3$) : (keep_$lvl+1$_$4*i$_$4*i+1$ | keep_$lvl+1$_$4*i+2$_$4*i+3$);
|
||||
$$ end
|
||||
$$ nr = nr + 1
|
||||
$$ if nr > 15 then nr = 0 end
|
||||
$$ end
|
||||
$$end
|
||||
|
||||
o := (1<<keep_0_0_1);
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// main WFC algorithm
|
||||
|
||||
algorithm wfc(
|
||||
output uint16 addr,
|
||||
output uint$L$ data,
|
||||
input uint16 seed
|
||||
)
|
||||
{
|
||||
// all sites, initialized so that everything is possible
|
||||
$$for i=1,N*N do
|
||||
uint$L$ grid_$i-1$ = $ones$;
|
||||
$$end
|
||||
$$for i=1,N*N do
|
||||
uint$L$ new_grid_$i-1$ = uninitialized;
|
||||
uint1 nstable_$i-1$ = uninitialized;
|
||||
$$end
|
||||
|
||||
// all rule-processors
|
||||
$$for i=1,N*N do
|
||||
$$ l,r,t,b = neighbors(i-1)
|
||||
wfc_rule_processor proc_$i-1$(
|
||||
site <:: grid_$i-1$,
|
||||
left <:: grid_$l$,
|
||||
right <:: grid_$r$,
|
||||
top <:: grid_$t$,
|
||||
bottom <:: grid_$b$,
|
||||
newsite :> new_grid_$i-1$,
|
||||
nstable :> nstable_$i-1$
|
||||
);
|
||||
$$end
|
||||
|
||||
// algorithm for choosing a label
|
||||
uint$L$ site = uninitialized;
|
||||
uint$L$ choice = uninitialized;
|
||||
makeAChoice chooser(
|
||||
i <:: site,
|
||||
rand <:: rand,
|
||||
o :> choice
|
||||
);
|
||||
|
||||
uint$N*N$ nstable_reduce := {
|
||||
$$for i=0,N*N-2 do
|
||||
nstable_$i$,
|
||||
$$end
|
||||
nstable_$N*N-1$
|
||||
};
|
||||
|
||||
// next entry to be collapsed
|
||||
uint16 next = 0;
|
||||
// random
|
||||
uint16 rand = 0;
|
||||
|
||||
// grid updates
|
||||
$$for i=1,N*N do
|
||||
grid_$i-1$ := new_grid_$i-1$;
|
||||
$$end
|
||||
|
||||
rand = seed + 7919;
|
||||
|
||||
__display("wfc start");
|
||||
|
||||
// while not fully resolved ...
|
||||
while (next < $N*N$) {
|
||||
|
||||
// choose
|
||||
{
|
||||
switch (next) {
|
||||
default: { site = 0; }
|
||||
$$for i=1,N*N do
|
||||
case $i-1$: { site = grid_$i-1$; }
|
||||
$$end
|
||||
}
|
||||
++: // wait for choice to be made, then store
|
||||
switch (next) {
|
||||
default: { }
|
||||
$$for i=1,N*N do
|
||||
case $i-1$: { grid_$i-1$ = choice; }
|
||||
$$end
|
||||
}
|
||||
}
|
||||
|
||||
// wait propagate
|
||||
while (nstable_reduce) { }
|
||||
|
||||
// display the grid
|
||||
__display("-----");
|
||||
$$for j=1,N do
|
||||
__display("%x %x %x %x %x %x %x %x",
|
||||
$$for i=1,N-1 do
|
||||
grid_$(i-1)+(j-1)*N$,
|
||||
$$end
|
||||
grid_$(N-1)+(j-1)*N$
|
||||
);
|
||||
$$end
|
||||
|
||||
rand = rand * 31421 + 6927;
|
||||
next = next + 1;
|
||||
}
|
||||
|
||||
// write to output
|
||||
next = 0;
|
||||
while (next < $N*N$) {
|
||||
addr = next;
|
||||
switch (next) {
|
||||
default: { }
|
||||
$$for i=1,N*N do
|
||||
case $i-1$: { data = grid_$i-1$; }
|
||||
$$end
|
||||
}
|
||||
next = next + 1;
|
||||
}
|
||||
|
||||
__display("wfc done");
|
||||
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
|
||||
algorithm frame_display(
|
||||
input uint10 pix_x,
|
||||
input uint10 pix_y,
|
||||
input uint1 pix_active,
|
||||
input uint1 pix_vblank,
|
||||
$$if not SIMULATION then
|
||||
input uint$NUM_BTNS$ btns,
|
||||
$$end
|
||||
output! uint$color_depth$ pix_r,
|
||||
output! uint$color_depth$ pix_g,
|
||||
output! uint$color_depth$ pix_b
|
||||
) <autorun> {
|
||||
|
||||
brom uint18 tiles[$16*16*L$] = {
|
||||
$$for i=1,L do
|
||||
$$write_image_in_table(PROBLEM .. 'tile_' .. string.format('%02d',i-1) .. '.tga',6)
|
||||
$$end
|
||||
};
|
||||
|
||||
simple_dualport_bram uint$L$ result[$N*N$] = uninitialized;
|
||||
|
||||
uint16 iter = 0;
|
||||
$$if not SIMULATION then
|
||||
uint$NUM_BTNS$ reg_btns = 0;
|
||||
$$end
|
||||
|
||||
wfc wfc1(
|
||||
addr :> result.addr1,
|
||||
data :> result.wdata1,
|
||||
seed <: iter
|
||||
);
|
||||
|
||||
pix_r := 0; pix_g := 0; pix_b := 0;
|
||||
|
||||
$$if not SIMULATION then
|
||||
reg_btns ::= btns;
|
||||
$$end
|
||||
|
||||
result.wenable1 = 1;
|
||||
|
||||
result.addr0 = 0;
|
||||
|
||||
// ---- display result
|
||||
while (1) {
|
||||
uint8 tile = 0;
|
||||
while (pix_vblank == 0) {
|
||||
if (pix_active) {
|
||||
// set rgb data
|
||||
pix_b = pix_x > 15 ? tiles.rdata[ 0,6] : 0;
|
||||
pix_g = pix_x > 15 ? tiles.rdata[ 6,6] : 0;
|
||||
pix_r = pix_x > 15 ? tiles.rdata[12,6] : 0;
|
||||
// ^^^^^^^^^^^ hides a defect on first tile of each row ... yeah, well ...
|
||||
{
|
||||
// read next pixel
|
||||
uint10 x = uninitialized;
|
||||
uint10 y = uninitialized;
|
||||
x = (pix_x == 639) ? 0 : pix_x+1;
|
||||
y = (pix_x == 639) ? pix_y+1 : pix_y;
|
||||
tiles .addr = (x&15) + ((y&15)<<4) + (tile<<8);
|
||||
// read next tile
|
||||
if ((pix_x&15) == 13) {
|
||||
// read grid ahead of vga beam
|
||||
result.addr0 = (((pix_x>>4)+1)&$N-1$) + (((pix_y>>4)&$N-1$)<<$Nlog$);
|
||||
} else { if ((pix_x&15) == 14) {
|
||||
// select next tile
|
||||
switch (result.rdata0) {
|
||||
default: { }
|
||||
$$for i=1,L do
|
||||
case $L$d$1<<(i-1)$: { tile = $i-1$; }
|
||||
$$end
|
||||
}
|
||||
} }
|
||||
}
|
||||
}
|
||||
}
|
||||
$$if not SIMULATION then
|
||||
if (reg_btns[1,1] != 0) {
|
||||
$$else
|
||||
if (1) {
|
||||
$$end
|
||||
while (1) {
|
||||
|
||||
() <- wfc1 <- ();
|
||||
|
||||
iter = iter + 1;
|
||||
|
||||
if (result.rdata0 != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wait for sync
|
||||
while (pix_vblank == 1) {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -------------------------
|
Loading…
Reference in New Issue
Block a user