From c322debb7bae40bebf53672d555870e86a467e0d Mon Sep 17 00:00:00 2001 From: Peder Bergebakken Sundt Date: Sat, 24 Jun 2023 15:01:18 +0200 Subject: [PATCH] Initial commit --- .envrc | 1 + .gitignore | 2 + shell.nix | 15 ++ syntax-example.si | 58 ++++++++ test.si | 10 ++ wfc_basic.si | 363 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 449 insertions(+) create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 shell.nix create mode 100644 syntax-example.si create mode 100644 test.si create mode 100644 wfc_basic.si diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..1d953f4 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use nix diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3cbb894 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +result +BUILD/ diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..16d98aa --- /dev/null +++ b/shell.nix @@ -0,0 +1,15 @@ +{ pkgs ? import {} }: +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 + ]; +} diff --git a/syntax-example.si b/syntax-example.si new file mode 100644 index 0000000..312ee39 --- /dev/null +++ b/syntax-example.si @@ -0,0 +1,58 @@ +$$Period = 1 / Frequency; +$$NSPerClock = 1000000000 * Period; +$$ClocksPerMS = math.floor( 1000000 / NSPerClock ); + +algorithm Debounce( input uint1 Source, output uint1 Dest ) { + 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; + } +} diff --git a/test.si b/test.si new file mode 100644 index 0000000..5acd2d9 --- /dev/null +++ b/test.si @@ -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; + } + } +} diff --git a/wfc_basic.si b/wfc_basic.si new file mode 100644 index 0000000..a7d962c --- /dev/null +++ b/wfc_basic.si @@ -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< 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< 15 then nr = 0 end +$$ end +$$end + + o := (1< 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 +) { + + 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) {} + } + +} + +// -------------------------