diff --git a/doc/notes.txt b/doc/notes.txt index c887ce72..eb3459c6 100644 --- a/doc/notes.txt +++ b/doc/notes.txt @@ -195,6 +195,7 @@ TODO: - don't include start/end line on platforms w/o raster timing - BIOS symbols - show current tool for file +- download non-text incbin source file Probing - probe log doesn't start @ reset diff --git a/presets/verilog/copperbars.ice b/presets/verilog/copperbars.ice new file mode 100644 index 00000000..4098f7f7 --- /dev/null +++ b/presets/verilog/copperbars.ice @@ -0,0 +1,102 @@ + + +// ------------------------- + +$include('ntsc.ice') + +// ------------------------- + +algorithm frame_display( + input uint10 pix_x, + input uint10 pix_y, + input uint1 pix_active, + input uint1 pix_vblank, + output! uint$color_depth$ pix_r, + output! uint$color_depth$ pix_g, + output! uint$color_depth$ pix_b +) { + + uint7 wave[64] = { +$$for i=0,63 do + $math.floor(127.0 * (0.5+0.5*math.cos(math.pi + 2*math.pi*i/63)))$, +$$end + }; + + uint$color_depth$ v = 0; + uint6 frame = 0; + int9 pos[4] = {0,0,0,0}; + + pix_r := 0; pix_g := 0; pix_b := 0; + // ---------- show time! + while (1) { + + // display frame + while (pix_vblank == 0) { + if (pix_active) { + 4x { + if (pix_y + 20 > pos[__id] && pix_y < pos[__id] + 20) { + v = ((wave[pix_y-pos[__id] + 32]>>1) * (__id+5)) >> 3; + pix_r = v*4; + pix_g = v*3; + pix_b = v*2; + } + } + } + } + // prepare next + frame = frame + 1; + 4x { + pos[__id] = $240 - 127$ + (wave[(frame + (__id << 3)) & 63] << 1); + } + // wait for sync + while (pix_vblank == 1) {} + } +} + +// ------------------------- + +algorithm main( + output! uint$color_depth$ video_r, + output! uint$color_depth$ video_g, + output! uint$color_depth$ video_b, + output! uint1 video_hs, + output! uint1 video_vs +) +<@clock,!reset> +{ + + uint1 active = 0; + uint1 vblank = 0; + uint10 pix_x = 0; + uint10 pix_y = 0; + + ntsc ntsc_driver ( + ntsc_hs :> video_hs, + ntsc_vs :> video_vs, + active :> active, + vblank :> vblank, + ntsc_x :> pix_x, + ntsc_y :> pix_y + ); + + frame_display display ( + pix_x <: pix_x, + pix_y <: pix_y, + pix_active <: active, + pix_vblank <: vblank, + pix_r :> video_r, + pix_g :> video_g, + pix_b :> video_b + ); + + uint8 frame = 0; + + // forever + while (1) { + + while (vblank == 0) { } + + frame = frame + 1; + + } +} diff --git a/presets/verilog/font_cp437_8x8.ice b/presets/verilog/font_cp437_8x8.ice new file mode 100644 index 00000000..97550575 --- /dev/null +++ b/presets/verilog/font_cp437_8x8.ice @@ -0,0 +1,259 @@ + +brom uint8 font_cp437_8x8[2048] = { +8h00,8h00,8h00,8h00,8h00,8h00,8h00,8h00, //0 +8h7e,8h81,8ha5,8h81,8hbd,8h99,8h81,8h7e, //1 +8h7e,8hff,8hdb,8hff,8hc3,8he7,8hff,8h7e, //2 +8h6c,8hfe,8hfe,8hfe,8h7c,8h38,8h10,8h00, //3 +8h10,8h38,8h7c,8hfe,8h7c,8h38,8h10,8h00, //4 +8h38,8h7c,8h38,8hfe,8hfe,8hd6,8h10,8h38, //5 +8h10,8h10,8h38,8h7c,8hfe,8h7c,8h10,8h38, //6 +8h00,8h00,8h18,8h3c,8h3c,8h18,8h00,8h00, //7 +8hff,8hff,8he7,8hc3,8hc3,8he7,8hff,8hff, //8 +8h00,8h3c,8h66,8h42,8h42,8h66,8h3c,8h00, //9 +8hff,8hc3,8h99,8hbd,8hbd,8h99,8hc3,8hff, //10 +8h0f,8h07,8h0f,8h7d,8hcc,8hcc,8hcc,8h78, //11 +8h3c,8h66,8h66,8h66,8h3c,8h18,8h7e,8h18, //12 +8h3f,8h33,8h3f,8h30,8h30,8h70,8hf0,8he0, //13 +8h7f,8h63,8h7f,8h63,8h63,8h67,8he6,8hc0, //14 +8h99,8h5a,8h3c,8he7,8he7,8h3c,8h5a,8h99, //15 +8h80,8he0,8hf8,8hfe,8hf8,8he0,8h80,8h00, //16 +8h02,8h0e,8h3e,8hfe,8h3e,8h0e,8h02,8h00, //17 +8h18,8h3c,8h7e,8h18,8h18,8h7e,8h3c,8h18, //18 +8h66,8h66,8h66,8h66,8h66,8h00,8h66,8h00, //19 +8h7f,8hdb,8hdb,8h7b,8h1b,8h1b,8h1b,8h00, //20 +8h7e,8hc3,8h78,8hcc,8hcc,8h78,8h8c,8hf8, //21 +8h00,8h00,8h00,8h00,8h7e,8h7e,8h7e,8h00, //22 +8h18,8h3c,8h7e,8h18,8h7e,8h3c,8h18,8hff, //23 +8h18,8h3c,8h7e,8h18,8h18,8h18,8h18,8h00, //24 +8h18,8h18,8h18,8h18,8h7e,8h3c,8h18,8h00, //25 +8h00,8h18,8h0c,8hfe,8h0c,8h18,8h00,8h00, //26 +8h00,8h30,8h60,8hfe,8h60,8h30,8h00,8h00, //27 +8h00,8h00,8hc0,8hc0,8hc0,8hfe,8h00,8h00, //28 +8h00,8h24,8h66,8hff,8h66,8h24,8h00,8h00, //29 +8h00,8h18,8h3c,8h7e,8hff,8hff,8h00,8h00, //30 +8h00,8hff,8hff,8h7e,8h3c,8h18,8h00,8h00, //31 +8h00,8h00,8h00,8h00,8h00,8h00,8h00,8h00, //32 +8h30,8h78,8h78,8h30,8h30,8h00,8h30,8h00, //33 +8h6c,8h6c,8h6c,8h00,8h00,8h00,8h00,8h00, //34 +8h6c,8h6c,8hfe,8h6c,8hfe,8h6c,8h6c,8h00, //35 +8h30,8h7c,8hc0,8h78,8h0c,8hf8,8h30,8h00, //36 +8h00,8hc6,8hcc,8h18,8h30,8h66,8hc6,8h00, //37 +8h38,8h6c,8h38,8h76,8hdc,8hcc,8h76,8h00, //38 +8h60,8h60,8hc0,8h00,8h00,8h00,8h00,8h00, //39 +8h18,8h30,8h60,8h60,8h60,8h30,8h18,8h00, //40 +8h60,8h30,8h18,8h18,8h18,8h30,8h60,8h00, //41 +8h00,8h66,8h3c,8hff,8h3c,8h66,8h00,8h00, //42 +8h00,8h30,8h30,8hfc,8h30,8h30,8h00,8h00, //43 +8h00,8h00,8h00,8h00,8h00,8h70,8h30,8h60, //44 +8h00,8h00,8h00,8hfc,8h00,8h00,8h00,8h00, //45 +8h00,8h00,8h00,8h00,8h00,8h30,8h30,8h00, //46 +8h06,8h0c,8h18,8h30,8h60,8hc0,8h80,8h00, //47 +8h78,8hcc,8hdc,8hfc,8hec,8hcc,8h78,8h00, //48 +8h30,8hf0,8h30,8h30,8h30,8h30,8hfc,8h00, //49 +8h78,8hcc,8h0c,8h38,8h60,8hcc,8hfc,8h00, //50 +8h78,8hcc,8h0c,8h38,8h0c,8hcc,8h78,8h00, //51 +8h1c,8h3c,8h6c,8hcc,8hfe,8h0c,8h0c,8h00, //52 +8hfc,8hc0,8hf8,8h0c,8h0c,8hcc,8h78,8h00, //53 +8h38,8h60,8hc0,8hf8,8hcc,8hcc,8h78,8h00, //54 +8hfc,8hcc,8h0c,8h18,8h30,8h60,8h60,8h00, //55 +8h78,8hcc,8hcc,8h78,8hcc,8hcc,8h78,8h00, //56 +8h78,8hcc,8hcc,8h7c,8h0c,8h18,8h70,8h00, //57 +8h00,8h00,8h30,8h30,8h00,8h30,8h30,8h00, //58 +8h00,8h00,8h30,8h30,8h00,8h70,8h30,8h60, //59 +8h18,8h30,8h60,8hc0,8h60,8h30,8h18,8h00, //60 +8h00,8h00,8hfc,8h00,8hfc,8h00,8h00,8h00, //61 +8h60,8h30,8h18,8h0c,8h18,8h30,8h60,8h00, //62 +8h78,8hcc,8h0c,8h18,8h30,8h00,8h30,8h00, //63 +8h7c,8hc6,8hde,8hde,8hde,8hc0,8h78,8h00, //64 +8h30,8h78,8hcc,8hcc,8hfc,8hcc,8hcc,8h00, //65 +8hfc,8h66,8h66,8h7c,8h66,8h66,8hfc,8h00, //66 +8h3c,8h66,8hc0,8hc0,8hc0,8h66,8h3c,8h00, //67 +8hfc,8h6c,8h66,8h66,8h66,8h6c,8hfc,8h00, //68 +8hfe,8h62,8h68,8h78,8h68,8h62,8hfe,8h00, //69 +8hfe,8h62,8h68,8h78,8h68,8h60,8hf0,8h00, //70 +8h3c,8h66,8hc0,8hc0,8hce,8h66,8h3e,8h00, //71 +8hcc,8hcc,8hcc,8hfc,8hcc,8hcc,8hcc,8h00, //72 +8h78,8h30,8h30,8h30,8h30,8h30,8h78,8h00, //73 +8h1e,8h0c,8h0c,8h0c,8hcc,8hcc,8h78,8h00, //74 +8he6,8h66,8h6c,8h78,8h6c,8h66,8he6,8h00, //75 +8hf0,8h60,8h60,8h60,8h62,8h66,8hfe,8h00, //76 +8hc6,8hee,8hfe,8hd6,8hc6,8hc6,8hc6,8h00, //77 +8hc6,8he6,8hf6,8hde,8hce,8hc6,8hc6,8h00, //78 +8h38,8h6c,8hc6,8hc6,8hc6,8h6c,8h38,8h00, //79 +8hfc,8h66,8h66,8h7c,8h60,8h60,8hf0,8h00, //80 +8h78,8hcc,8hcc,8hcc,8hdc,8h78,8h1c,8h00, //81 +8hfc,8h66,8h66,8h7c,8h78,8h6c,8he6,8h00, //82 +8h78,8hcc,8he0,8h38,8h1c,8hcc,8h78,8h00, //83 +8hfc,8hb4,8h30,8h30,8h30,8h30,8h78,8h00, //84 +8hcc,8hcc,8hcc,8hcc,8hcc,8hcc,8hfc,8h00, //85 +8hcc,8hcc,8hcc,8hcc,8hcc,8h78,8h30,8h00, //86 +8hc6,8hc6,8hc6,8hd6,8hfe,8hee,8hc6,8h00, //87 +8hc6,8hc6,8h6c,8h38,8h6c,8hc6,8hc6,8h00, //88 +8hcc,8hcc,8hcc,8h78,8h30,8h30,8h78,8h00, //89 +8hfe,8hcc,8h98,8h30,8h62,8hc6,8hfe,8h00, //90 +8h78,8h60,8h60,8h60,8h60,8h60,8h78,8h00, //91 +8hc0,8h60,8h30,8h18,8h0c,8h06,8h02,8h00, //92 +8h78,8h18,8h18,8h18,8h18,8h18,8h78,8h00, //93 +8h10,8h38,8h6c,8hc6,8h00,8h00,8h00,8h00, //94 +8h00,8h00,8h00,8h00,8h00,8h00,8h00,8hff, //95 +8h30,8h30,8h18,8h00,8h00,8h00,8h00,8h00, //96 +8h00,8h00,8h78,8h0c,8h7c,8hcc,8h76,8h00, //97 +8he0,8h60,8h7c,8h66,8h66,8h66,8hbc,8h00, //98 +8h00,8h00,8h78,8hcc,8hc0,8hcc,8h78,8h00, //99 +8h1c,8h0c,8h0c,8h7c,8hcc,8hcc,8h76,8h00, //100 +8h00,8h00,8h78,8hcc,8hfc,8hc0,8h78,8h00, //101 +8h38,8h6c,8h60,8hf0,8h60,8h60,8hf0,8h00, //102 +8h00,8h00,8h76,8hcc,8hcc,8h7c,8h0c,8hf8, //103 +8he0,8h60,8h6c,8h76,8h66,8h66,8he6,8h00, //104 +8h30,8h00,8h70,8h30,8h30,8h30,8h78,8h00, //105 +8h18,8h00,8h78,8h18,8h18,8h18,8hd8,8h70, //106 +8he0,8h60,8h66,8h6c,8h78,8h6c,8he6,8h00, //107 +8h70,8h30,8h30,8h30,8h30,8h30,8h78,8h00, //108 +8h00,8h00,8hec,8hfe,8hd6,8hc6,8hc6,8h00, //109 +8h00,8h00,8hf8,8hcc,8hcc,8hcc,8hcc,8h00, //110 +8h00,8h00,8h78,8hcc,8hcc,8hcc,8h78,8h00, //111 +8h00,8h00,8hdc,8h66,8h66,8h7c,8h60,8hf0, //112 +8h00,8h00,8h76,8hcc,8hcc,8h7c,8h0c,8h1e, //113 +8h00,8h00,8hd8,8h6c,8h6c,8h60,8hf0,8h00, //114 +8h00,8h00,8h7c,8hc0,8h78,8h0c,8hf8,8h00, //115 +8h10,8h30,8h7c,8h30,8h30,8h34,8h18,8h00, //116 +8h00,8h00,8hcc,8hcc,8hcc,8hcc,8h76,8h00, //117 +8h00,8h00,8hcc,8hcc,8hcc,8h78,8h30,8h00, //118 +8h00,8h00,8hc6,8hc6,8hd6,8hfe,8h6c,8h00, //119 +8h00,8h00,8hc6,8h6c,8h38,8h6c,8hc6,8h00, //120 +8h00,8h00,8hcc,8hcc,8hcc,8h7c,8h0c,8hf8, //121 +8h00,8h00,8hfc,8h98,8h30,8h64,8hfc,8h00, //122 +8h1c,8h30,8h30,8he0,8h30,8h30,8h1c,8h00, //123 +8h18,8h18,8h18,8h00,8h18,8h18,8h18,8h00, //124 +8he0,8h30,8h30,8h1c,8h30,8h30,8he0,8h00, //125 +8h76,8hdc,8h00,8h00,8h00,8h00,8h00,8h00, //126 +8h10,8h38,8h6c,8hc6,8hc6,8hc6,8hfe,8h00, //127 +8h78,8hcc,8hc0,8hcc,8h78,8h18,8h0c,8h78, //128 +8h00,8hcc,8h00,8hcc,8hcc,8hcc,8h7e,8h00, //129 +8h1c,8h00,8h78,8hcc,8hfc,8hc0,8h78,8h00, //130 +8h7e,8hc3,8h3c,8h06,8h3e,8h66,8h3f,8h00, //131 +8hcc,8h00,8h78,8h0c,8h7c,8hcc,8h7e,8h00, //132 +8he0,8h00,8h78,8h0c,8h7c,8hcc,8h7e,8h00, //133 +8h30,8h30,8h78,8h0c,8h7c,8hcc,8h7e,8h00, //134 +8h00,8h00,8h7c,8hc0,8hc0,8h7c,8h06,8h3c, //135 +8h7e,8hc3,8h3c,8h66,8h7e,8h60,8h3c,8h00, //136 +8hcc,8h00,8h78,8hcc,8hfc,8hc0,8h78,8h00, //137 +8he0,8h00,8h78,8hcc,8hfc,8hc0,8h78,8h00, //138 +8hcc,8h00,8h70,8h30,8h30,8h30,8h78,8h00, //139 +8h7c,8hc6,8h38,8h18,8h18,8h18,8h3c,8h00, //140 +8he0,8h00,8h70,8h30,8h30,8h30,8h78,8h00, //141 +8hcc,8h30,8h78,8hcc,8hcc,8hfc,8hcc,8h00, //142 +8h30,8h30,8h00,8h78,8hcc,8hfc,8hcc,8h00, //143 +8h1c,8h00,8hfc,8h60,8h78,8h60,8hfc,8h00, //144 +8h00,8h00,8h7f,8h0c,8h7f,8hcc,8h7f,8h00, //145 +8h3e,8h6c,8hcc,8hfe,8hcc,8hcc,8hce,8h00, //146 +8h78,8hcc,8h00,8h78,8hcc,8hcc,8h78,8h00, //147 +8h00,8hcc,8h00,8h78,8hcc,8hcc,8h78,8h00, //148 +8h00,8he0,8h00,8h78,8hcc,8hcc,8h78,8h00, //149 +8h78,8hcc,8h00,8hcc,8hcc,8hcc,8h7e,8h00, //150 +8h00,8he0,8h00,8hcc,8hcc,8hcc,8h7e,8h00, //151 +8h00,8hcc,8h00,8hcc,8hcc,8hfc,8h0c,8hf8, //152 +8hc6,8h38,8h7c,8hc6,8hc6,8h7c,8h38,8h00, //153 +8hcc,8h00,8hcc,8hcc,8hcc,8hcc,8h78,8h00, //154 +8h18,8h18,8h7e,8hc0,8hc0,8h7e,8h18,8h18, //155 +8h38,8h6c,8h64,8hf0,8h60,8he6,8hfc,8h00, //156 +8hcc,8hcc,8h78,8hfc,8h30,8hfc,8h30,8h00, //157 +8hf0,8hd8,8hd8,8hf4,8hcc,8hde,8hcc,8h0e, //158 +8h0e,8h1b,8h18,8h7e,8h18,8h18,8hd8,8h70, //159 +8h1c,8h00,8h78,8h0c,8h7c,8hcc,8h7e,8h00, //160 +8h38,8h00,8h70,8h30,8h30,8h30,8h78,8h00, //161 +8h00,8h1c,8h00,8h78,8hcc,8hcc,8h78,8h00, //162 +8h00,8h1c,8h00,8hcc,8hcc,8hcc,8h7e,8h00, //163 +8h00,8hf8,8h00,8hf8,8hcc,8hcc,8hcc,8h00, //164 +8hfc,8h00,8hcc,8hec,8hfc,8hdc,8hcc,8h00, //165 +8h3c,8h6c,8h6c,8h3e,8h00,8h7e,8h00,8h00, //166 +8h3c,8h66,8h66,8h3c,8h00,8h7e,8h00,8h00, //167 +8h30,8h00,8h30,8h60,8hc0,8hcc,8h78,8h00, //168 +8h00,8h00,8h00,8hfc,8hc0,8hc0,8h00,8h00, //169 +8h00,8h00,8h00,8hfc,8h0c,8h0c,8h00,8h00, //170 +8hc6,8hcc,8hd8,8h3e,8h63,8hce,8h98,8h1f, //171 +8hc6,8hcc,8hd8,8hf3,8h67,8hcf,8h9f,8h03, //172 +8h00,8h18,8h00,8h18,8h18,8h3c,8h3c,8h18, //173 +8h00,8h33,8h66,8hcc,8h66,8h33,8h00,8h00, //174 +8h00,8hcc,8h66,8h33,8h66,8hcc,8h00,8h00, //175 +8h22,8h88,8h22,8h88,8h22,8h88,8h22,8h88, //176 +8h55,8haa,8h55,8haa,8h55,8haa,8h55,8haa, //177 +8hdd,8h77,8hdd,8h77,8hdd,8h77,8hdd,8h77, //178 +8h18,8h18,8h18,8h18,8h18,8h18,8h18,8h18, //179 +8h18,8h18,8h18,8h18,8hf8,8h18,8h18,8h18, //180 +8h18,8h18,8hf8,8h18,8hf8,8h18,8h18,8h18, //181 +8h36,8h36,8h36,8h36,8hf6,8h36,8h36,8h36, //182 +8h00,8h00,8h00,8h00,8hfe,8h36,8h36,8h36, //183 +8h00,8h00,8hf8,8h18,8hf8,8h18,8h18,8h18, //184 +8h36,8h36,8hf6,8h06,8hf6,8h36,8h36,8h36, //185 +8h36,8h36,8h36,8h36,8h36,8h36,8h36,8h36, //186 +8h00,8h00,8hfe,8h06,8hf6,8h36,8h36,8h36, //187 +8h36,8h36,8hf6,8h06,8hfe,8h00,8h00,8h00, //188 +8h36,8h36,8h36,8h36,8hfe,8h00,8h00,8h00, //189 +8h18,8h18,8hf8,8h18,8hf8,8h00,8h00,8h00, //190 +8h00,8h00,8h00,8h00,8hf8,8h18,8h18,8h18, //191 +8h18,8h18,8h18,8h18,8h1f,8h00,8h00,8h00, //192 +8h18,8h18,8h18,8h18,8hff,8h00,8h00,8h00, //193 +8h00,8h00,8h00,8h00,8hff,8h18,8h18,8h18, //194 +8h18,8h18,8h18,8h18,8h1f,8h18,8h18,8h18, //195 +8h00,8h00,8h00,8h00,8hff,8h00,8h00,8h00, //196 +8h18,8h18,8h18,8h18,8hff,8h18,8h18,8h18, //197 +8h18,8h18,8h1f,8h18,8h1f,8h18,8h18,8h18, //198 +8h36,8h36,8h36,8h36,8h37,8h36,8h36,8h36, //199 +8h36,8h36,8h37,8h30,8h3f,8h00,8h00,8h00, //200 +8h00,8h00,8h3f,8h30,8h37,8h36,8h36,8h36, //201 +8h36,8h36,8hf7,8h00,8hff,8h00,8h00,8h00, //202 +8h00,8h00,8hff,8h00,8hf7,8h36,8h36,8h36, //203 +8h36,8h36,8h37,8h30,8h37,8h36,8h36,8h36, //204 +8h00,8h00,8hff,8h00,8hff,8h00,8h00,8h00, //205 +8h36,8h36,8hf7,8h00,8hf7,8h36,8h36,8h36, //206 +8h18,8h18,8hff,8h00,8hff,8h00,8h00,8h00, //207 +8h36,8h36,8h36,8h36,8hff,8h00,8h00,8h00, //208 +8h00,8h00,8hff,8h00,8hff,8h18,8h18,8h18, //209 +8h00,8h00,8h00,8h00,8hff,8h36,8h36,8h36, //210 +8h36,8h36,8h36,8h36,8h3f,8h00,8h00,8h00, //211 +8h18,8h18,8h1f,8h18,8h1f,8h00,8h00,8h00, //212 +8h00,8h00,8h1f,8h18,8h1f,8h18,8h18,8h18, //213 +8h00,8h00,8h00,8h00,8h3f,8h36,8h36,8h36, //214 +8h36,8h36,8h36,8h36,8hf7,8h36,8h36,8h36, //215 +8h18,8h18,8hff,8h00,8hff,8h18,8h18,8h18, //216 +8h18,8h18,8h18,8h18,8hf8,8h00,8h00,8h00, //217 +8h00,8h00,8h00,8h00,8h1f,8h18,8h18,8h18, //218 +8hff,8hff,8hff,8hff,8hff,8hff,8hff,8hff, //219 +8h00,8h00,8h00,8h00,8hff,8hff,8hff,8hff, //220 +8hf0,8hf0,8hf0,8hf0,8hf0,8hf0,8hf0,8hf0, //221 +8h0f,8h0f,8h0f,8h0f,8h0f,8h0f,8h0f,8h0f, //222 +8hff,8hff,8hff,8hff,8h00,8h00,8h00,8h00, //223 +8h00,8h00,8h76,8hdc,8hc8,8hdc,8h76,8h00, //224 +8h00,8h78,8hcc,8hf8,8hcc,8hf8,8hc0,8hc0, //225 +8h00,8hfe,8hc6,8hc0,8hc0,8hc0,8hc0,8h00, //226 +8h00,8hfe,8h6c,8h6c,8h6c,8h6c,8h6c,8h00, //227 +8hfe,8h66,8h30,8h18,8h30,8h66,8hfe,8h00, //228 +8h00,8h00,8h7e,8hcc,8hcc,8hcc,8h78,8h00, //229 +8h00,8h66,8h66,8h66,8h66,8h7c,8h60,8hc0, //230 +8h00,8h76,8hdc,8h18,8h18,8h18,8h18,8h00, //231 +8hfc,8h30,8h78,8hcc,8hcc,8h78,8h30,8hfc, //232 +8h38,8h6c,8hc6,8hfe,8hc6,8h6c,8h38,8h00, //233 +8h38,8h6c,8hc6,8hc6,8h6c,8h6c,8hee,8h00, //234 +8h1c,8h30,8h18,8h7c,8hcc,8hcc,8h78,8h00, //235 +8h00,8h00,8h7e,8hdb,8hdb,8h7e,8h00,8h00, //236 +8h06,8h0c,8h7e,8hdb,8hdb,8h7e,8h60,8hc0, //237 +8h3c,8h60,8hc0,8hfc,8hc0,8h60,8h3c,8h00, //238 +8h78,8hcc,8hcc,8hcc,8hcc,8hcc,8hcc,8h00, //239 +8h00,8hfc,8h00,8hfc,8h00,8hfc,8h00,8h00, //240 +8h30,8h30,8hfc,8h30,8h30,8h00,8hfc,8h00, //241 +8h60,8h30,8h18,8h30,8h60,8h00,8hfc,8h00, //242 +8h18,8h30,8h60,8h30,8h18,8h00,8hfc,8h00, //243 +8h0e,8h1b,8h1b,8h18,8h18,8h18,8h18,8h18, //244 +8h18,8h18,8h18,8h18,8h18,8hd8,8hd8,8h70, //245 +8h30,8h30,8h00,8hfc,8h00,8h30,8h30,8h00, //246 +8h00,8h72,8h9c,8h00,8h72,8h9c,8h00,8h00, //247 +8h38,8h6c,8h6c,8h38,8h00,8h00,8h00,8h00, //248 +8h00,8h00,8h00,8h18,8h18,8h00,8h00,8h00, //249 +8h00,8h00,8h00,8h00,8h18,8h00,8h00,8h00, //250 +8h0f,8h0c,8h0c,8h0c,8hec,8h6c,8h3c,8h1c, //251 +8h78,8h6c,8h6c,8h6c,8h6c,8h00,8h00,8h00, //252 +8h78,8h0c,8h38,8h60,8h7c,8h00,8h00,8h00, //253 +8h00,8h00,8h3c,8h3c,8h3c,8h3c,8h00,8h00, //254 +8h00,8h00,8h00,8h00,8h00,8h00,8h00,8h00 //255 +}; diff --git a/presets/verilog/life.ice b/presets/verilog/life.ice new file mode 100644 index 00000000..4922758a --- /dev/null +++ b/presets/verilog/life.ice @@ -0,0 +1,125 @@ + +$include('ntsc.ice') + +// ------------------------- + +algorithm frame_display( + input uint10 pix_x, + input uint10 pix_y, + input uint1 pix_active, + input uint1 pix_vblank, + output! uint$color_depth$ pix_r, + output! uint$color_depth$ pix_g, + output! uint$color_depth$ pix_b +) { + + $include('font_cp437_8x8.ice') + + // 256x256 cells (240 lines used) + dualport_bram uint1 cells[65536] = uninitialized; + // previous 2 rows + dualport_bram uint1 row1[256] = uninitialized; + dualport_bram uint1 row2[256] = uninitialized; + + // 3x3 pixel mask around x/y + uint9 neigh = 0; + + // offsets to X and Y coordinate + uint8 xx := pix_x[0,8]; + uint8 yy := pix_y[0,8]; + uint8 xxm3 := xx - 3; + uint8 xxm1 := xx - 1; + uint8 yym1 := yy - 1; + + // count # of live neigbors (up to 8) + uint3 ncount ::= + neigh[0,1] + neigh[1,1] + neigh[2,1] + + neigh[3,1] + neigh[5,1] + + neigh[6,1] + neigh[7,1] + neigh[8,1]; + + // pixel is set if: + // * 3 live neighbors + // * 2 live neigbors and was already alive + uint1 alive ::= (ncount == 3) || (ncount == 2 && neigh[4,1]); + + // by default r,g,b are set to zero + pix_r := 0; + pix_g := 0; + pix_b := 0; + + // set dual-port block RAM bus addresses (continuously) + row1.addr0 := xx; + row2.addr0 := xx; + cells.addr0 := {yy, xx}; + row1.addr1 := xxm1; + row2.addr1 := xxm1; + cells.addr1 := {yym1, xxm3}; + row1.wenable1 := 1; + row2.wenable1 := 1; + cells.wenable1 = 1; + + // ---------- show time! + while (1) { + // display frame + while (pix_vblank == 0) { + if (pix_active) { + // shift neighbor cells to the left by 1 pixel + // while adding right pix from row1/row2/cells array + neigh = { + neigh[6,2], row1.rdata0, + neigh[3,2], row2.rdata0, + neigh[0,2], cells.rdata0 + }; + // copy alive -> cells -> row2 -> row1 + row1.wdata1 = row2.rdata0; + row2.wdata1 = cells.rdata0; + cells.wdata1 = alive; + // set RGB color based on surroundings + pix_r = ncount * 31; + pix_g = neigh[4,1] * 255; + pix_b = alive * 255; + } + } + } +} + +// ------------------------- + +algorithm main( + output! uint$color_depth$ video_r, + output! uint$color_depth$ video_g, + output! uint$color_depth$ video_b, + output! uint1 video_hs, + output! uint1 video_vs +) +<@clock,!reset> +{ + + uint1 active = 0; + uint1 vblank = 0; + uint10 pix_x = 0; + uint10 pix_y = 0; + + ntsc ntsc_driver ( + ntsc_hs :> video_hs, + ntsc_vs :> video_vs, + active :> active, + vblank :> vblank, + ntsc_x :> pix_x, + ntsc_y :> pix_y + ); + + frame_display display ( + pix_x <: pix_x, + pix_y <: pix_y, + pix_active <: active, + pix_vblank <: vblank, + pix_r :> video_r, + pix_g :> video_g, + pix_b :> video_b + ); + + // forever + while (1) { + } +} diff --git a/presets/verilog/ntsc.ice b/presets/verilog/ntsc.ice new file mode 100755 index 00000000..7c8c2064 --- /dev/null +++ b/presets/verilog/ntsc.ice @@ -0,0 +1,80 @@ +// SL 2019-10 +// +// GNU AFFERO GENERAL PUBLIC LICENSE +// Version 3, 19 November 2007 +// +// A copy of the license full text is included in +// the distribution, please refer to it for details. + +algorithm ntsc( + output! uint1 ntsc_hs, + output! uint1 ntsc_vs, + output! uint1 active, + output! uint1 vblank, + output! uint10 ntsc_x, + output! uint10 ntsc_y +) { + + uint10 H_FRT_PORCH = 7; + uint10 H_SYNCH = 23; + uint10 H_BCK_PORCH = 23; + uint10 H_RES = 256; + + uint10 V_FRT_PORCH = 5; + uint10 V_SYNCH = 3; + uint10 V_BCK_PORCH = 14; + uint10 V_RES = 240; + + uint10 HS_START = 0; + uint10 HS_END = 0; + uint10 HA_START = 0; + uint10 H_END = 0; + + uint10 VS_START = 0; + uint10 VS_END = 0; + uint10 VA_START = 0; + uint10 V_END = 0; + + uint10 xcount = 0; + uint10 ycount = 0; + + HS_START := H_FRT_PORCH; + HS_END := H_FRT_PORCH + H_SYNCH; + HA_START := H_FRT_PORCH + H_SYNCH + H_BCK_PORCH; + H_END := H_FRT_PORCH + H_SYNCH + H_BCK_PORCH + H_RES; + + VS_START := V_FRT_PORCH; + VS_END := V_FRT_PORCH + V_SYNCH; + VA_START := V_FRT_PORCH + V_SYNCH + V_BCK_PORCH; + V_END := V_FRT_PORCH + V_SYNCH + V_BCK_PORCH + V_RES; + + ntsc_hs := ((xcount >= HS_START && xcount < HS_END)); + ntsc_vs := ((ycount >= VS_START && ycount < VS_END)); + + active := (xcount >= HA_START && xcount < H_END) + && (ycount >= VA_START && ycount < V_END); + vblank := (ycount < VA_START); + + xcount = 0; + ycount = 0; + + while (1) { + + ntsc_x = (active) ? xcount - HA_START : 0; + ntsc_y = (vblank) ? 0 : ycount - VA_START; + + if (xcount == H_END-1) { + xcount = 0; + if (ycount == V_END-1) { + ycount = 0; + } else { + ycount = ycount + 1; + } + } else { + xcount = xcount + 1; + } + } + +} + +// ------------------------- diff --git a/presets/verilog/rototexture.ice b/presets/verilog/rototexture.ice new file mode 100644 index 00000000..4ebfcf79 --- /dev/null +++ b/presets/verilog/rototexture.ice @@ -0,0 +1,141 @@ + +$include('ntsc.ice') + +// SL 2020-04-22 +// A rotating texture using BRAM + +// ------------------------- + +algorithm frame_display( + input uint10 pix_x, + input uint10 pix_y, + input uint1 pix_active, + input uint1 pix_vblank, + output! uint$color_depth$ pix_r, + output! uint$color_depth$ pix_g, + output! uint$color_depth$ pix_b +) { + + uint8 frame = 0; + uint8 angle = 0; + int20 u = 0; + int20 v = 0; + int20 cos = 0; + int20 sin = 0; + int20 cornerx = 320; + int20 cornery = 240; + //int20 cornerx = -320; + //int20 cornery = -240; + int20 corneru = 0; + int20 cornerv = 0; + int20 deltau_x = 0; + int20 deltau_y = 0; + int20 deltav_x = 0; + int20 deltav_y = 0; + + brom uint18 tbl[$32*32$] = { +$$write_image_in_table('tile.tga',6) + }; + + brom int10 cosine[256] = { +$$for i=0,255 do + $math.floor(511.0 * math.cos(2*math.pi*i/255))$, +$$end + }; + + pix_r := 0; pix_g := 0; pix_b := 0; + // ---------- show time! + while (1) { + // display frame + while (pix_vblank == 0) { + if (pix_active) { + pix_b = tbl.rdata[0,6]<<2; + pix_g = tbl.rdata[6,6]<<2; + pix_r = tbl.rdata[12,6]<<2; + // update u,v + if (pix_x == 0) { + u = corneru; + v = cornerv; + } else { + if (pix_x == 255) { + corneru = corneru + deltau_y; + cornerv = cornerv + deltav_y; + } else { + u = u + deltau_x; + v = v + deltav_x; + } + } + // tbl bram access + tbl.addr = ((u>>11)&31) + (((v>>11)&31)<<5); + // access during loop (one cycle to go back) + } + } + // prepare next (we are in vblank, there is time) + cosine.addr = frame; + frame = frame + 1; +++: + angle = ((512+cosine.rdata) >> 2); + cosine.addr = angle; +++: // sine bram access + cos = cosine.rdata; + cosine.addr = angle + 64; +++: // sine bram access + sin = cosine.rdata; + // prepare scanline with mapping + corneru = - ((cornerx * cos) - (cornery * sin)); + cornerv = - ((cornerx * sin) + (cornery * cos)); + //corneru = ((cornerx * cos) - (cornery * sin)); + //cornerv = ((cornerx * sin) + (cornery * cos)); + deltau_x = cos; + deltau_y = - sin; + deltav_x = sin; + deltav_y = cos; + u = corneru; + v = cornerv; + // wait for sync + while (pix_vblank == 1) {} + } + +} + + +// ------------------------- + +algorithm main( + output! uint$color_depth$ video_r, + output! uint$color_depth$ video_g, + output! uint$color_depth$ video_b, + output! uint1 video_hs, + output! uint1 video_vs +) +<@clock,!reset> +{ + + uint1 active = 0; + uint1 vblank = 0; + uint10 pix_x = 0; + uint10 pix_y = 0; + + ntsc ntsc_driver ( + ntsc_hs :> video_hs, + ntsc_vs :> video_vs, + active :> active, + vblank :> vblank, + ntsc_x :> pix_x, + ntsc_y :> pix_y + ); + + frame_display display ( + pix_x <: pix_x, + pix_y <: pix_y, + pix_active <: active, + pix_vblank <: vblank, + pix_r :> video_r, + pix_g :> video_g, + pix_b :> video_b + ); + + // forever + while (1) { + } +} diff --git a/presets/verilog/skeleton.silice b/presets/verilog/skeleton.silice new file mode 100644 index 00000000..72264962 --- /dev/null +++ b/presets/verilog/skeleton.silice @@ -0,0 +1,83 @@ + +// ------------------------- + +$include('ntsc.ice') + +// ------------------------- + +algorithm frame_display( + input uint10 pix_x, + input uint10 pix_y, + input uint1 pix_active, + input uint1 pix_vblank, + output! uint$color_depth$ pix_r, + output! uint$color_depth$ pix_g, + output! uint$color_depth$ pix_b +) { + + uint8 frame = 0; + + // by default r,g,b are set to zero + pix_r := 0; + pix_g := 0; + pix_b := 0; + + // ---------- show time! + while (1) { + // display frame + while (pix_vblank == 0) { + if (pix_active) { + pix_b = frame << 2; + pix_g = pix_y[0,$color_depth$]; + pix_r = pix_x[0,$color_depth$]; + } + } + while (pix_vblank == 1) {} // wait for sync + frame = frame + 1; + } +} + +// ------------------------- + +algorithm main( + // NTSC + output! uint$color_depth$ video_r, + output! uint$color_depth$ video_g, + output! uint$color_depth$ video_b, + output! uint1 video_hs, + output! uint1 video_vs +) +<@clock,!reset> +{ + + uint1 active = 0; + uint1 vblank = 0; + uint10 pix_x = 0; + uint10 pix_y = 0; + + ntsc ntsc_driver ( + ntsc_hs :> video_hs, + ntsc_vs :> video_vs, + active :> active, + vblank :> vblank, + ntsc_x :> pix_x, + ntsc_y :> pix_y + ); + + frame_display display ( + pix_x <: pix_x, + pix_y <: pix_y, + pix_active <: active, + pix_vblank <: vblank, + pix_r :> video_r, + pix_g :> video_g, + pix_b :> video_b + ); + + // forever + while (1) { + + while (vblank == 0) { } + + } +} diff --git a/presets/verilog/test_pattern.ice b/presets/verilog/test_pattern.ice new file mode 100644 index 00000000..9b1132a0 --- /dev/null +++ b/presets/verilog/test_pattern.ice @@ -0,0 +1,81 @@ + +// ------------------------- + +$include('ntsc.ice') + +// ------------------------- + +algorithm frame_display( + input uint10 pix_x, + input uint10 pix_y, + input uint1 pix_active, + input uint1 pix_vblank, + output! uint$color_depth$ pix_r, + output! uint$color_depth$ pix_g, + output! uint$color_depth$ pix_b +) { + // by default r,g,b are set to zero + pix_r := 0; + pix_g := 0; + pix_b := 0; + // ---------- show time! + while (1) { + // display frame + while (pix_vblank == 0) { + if (pix_active) { + pix_b = pix_x[0,$color_depth$]<<3; + pix_g = pix_y[0,$color_depth$]<<2; + pix_r = pix_x[0,$color_depth$]<<1; + } + } + while (pix_vblank == 1) {} // wait for sync + } +} + +// ------------------------- + +algorithm main( + output! uint$color_depth$ video_r, + output! uint$color_depth$ video_g, + output! uint$color_depth$ video_b, + output! uint1 video_hs, + output! uint1 video_vs +) +<@clock,!reset> +{ + + uint1 active = 0; + uint1 vblank = 0; + uint10 pix_x = 0; + uint10 pix_y = 0; + + ntsc ntsc_driver ( + ntsc_hs :> video_hs, + ntsc_vs :> video_vs, + active :> active, + vblank :> vblank, + ntsc_x :> pix_x, + ntsc_y :> pix_y + ); + + frame_display display ( + pix_x <: pix_x, + pix_y <: pix_y, + pix_active <: active, + pix_vblank <: vblank, + pix_r :> video_r, + pix_g :> video_g, + pix_b :> video_b + ); + + uint8 frame = 0; + + // forever + while (1) { + + while (vblank == 0) { } + + frame = frame + 1; + + } +} diff --git a/presets/verilog/tile.tga b/presets/verilog/tile.tga new file mode 100755 index 00000000..483edeaa Binary files /dev/null and b/presets/verilog/tile.tga differ diff --git a/src/ide/project.ts b/src/ide/project.ts index d14f69b9..81041786 100644 --- a/src/ide/project.ts +++ b/src/ide/project.ts @@ -86,6 +86,11 @@ export class CodeProject { while (m = re1.exec(text)) { this.pushAllFiles(files, m[2]); } + // for Silice + let re1a = /^\s*\$(include|\$dofile|\$write_image_in_table)\('(.+?)'/gmi; + while (m = re1a.exec(text)) { + this.pushAllFiles(files, m[2]); + } // include .arch (json) statements let re2 = /^\s*([.]arch)\s+(\w+)/gmi; while (m = re2.exec(text)) { @@ -104,7 +109,7 @@ export class CodeProject { this.pushAllFiles(files, m[2]); } // for .c -- //#resource "file" (or ;resource or #resource) - let re3 = /^\s*([;]|[/][/])#resource\s+"(.+?)"/gm; + let re3 = /^\s*([;']|[/][/])#resource\s+"(.+?)"/gm; while (m = re3.exec(text)) { this.pushAllFiles(files, m[2]); } diff --git a/src/ide/ui.ts b/src/ide/ui.ts index c268d47c..32dbf098 100644 --- a/src/ide/ui.ts +++ b/src/ide/ui.ts @@ -82,6 +82,7 @@ var TOOL_TO_SOURCE_STYLE = { 'inform6': 'inform6', 'fastbasic': 'fastbasic', 'basic': 'basic', + 'silice': 'verilog', } function gaEvent(category:string, action:string, label?:string, value?:string) { diff --git a/src/ide/waveform.ts b/src/ide/waveform.ts index b3c1510b..0cac91c0 100644 --- a/src/ide/waveform.ts +++ b/src/ide/waveform.ts @@ -67,7 +67,7 @@ export class WaveformView { w: width, h: $(this.parent).height(), itemHeight: rowHeight, - totalRows: this.meta.length, + totalRows: this.meta.length+1, generatorFn: (row : number) => { var metarow = this.meta[row]; // TODO: why null? var s = metarow != null ? metarow.label : ""; diff --git a/src/platform/verilog.ts b/src/platform/verilog.ts index 77b98b09..91805b06 100644 --- a/src/platform/verilog.ts +++ b/src/platform/verilog.ts @@ -97,6 +97,9 @@ export function VL_GTES_III(x,lbits,y,lhs,rhs) { export function VL_DIV_III(lbits,lhs,rhs) { return (((rhs)==0)?0:(lhs)/(rhs)); } +export function VL_MULS_III(lbits,lhs,rhs) { + return (((rhs)==0)?0:(lhs)*(rhs)); } + export function VL_MODDIV_III(lbits,lhs,rhs) { return (((rhs)==0)?0:(lhs)%(rhs)); } @@ -120,11 +123,11 @@ export function VL_REDXOR_32(r) { export var VL_WRITEF = console.log; // TODO: $write export function vl_finish(filename,lineno,hier) { - console.log("Finished at " + filename + ":" + lineno, hier); + if (!vl_finished) console.log("Finished at " + filename + ":" + lineno, hier); vl_finished = true; } export function vl_stop(filename,lineno,hier) { - console.log("Stopped at " + filename + ":" + lineno, hier); + if (!vl_stopped) console.log("Stopped at " + filename + ":" + lineno, hier); vl_stopped = true; } @@ -534,7 +537,8 @@ var VerilogPlatform = function(mainElement, options) { if (inspect) { inspect_data[frameidx] = inspect_obj[inspect_sym]; } - idata[frameidx] = RGBLOOKUP[gen.rgb & 15]; + let rgb = gen.rgb; + idata[frameidx] = rgb & 0x80000000 ? rgb : RGBLOOKUP[rgb & 15]; frameidx++; } } else if (!framehsync && gen.hsync) { @@ -744,19 +748,22 @@ var VerilogPlatform = function(mainElement, options) { gen.tick2(); } getToolForFilename(fn) { - if (fn.endsWith("asm")) - return "jsasm"; - else - return "verilator"; + if (fn.endsWith(".asm")) return "jsasm"; + else if (fn.endsWith(".ice")) return "silice"; + else return "verilator"; } getDefaultExtension() { return ".v"; }; inspect(name:string) : string { if (!gen) return; - if (name && !name.match(/^\w+$/)) return; + if (name) name = name.replace('.','_'); + if (!name || !name.match(/^\w+$/)) { + inspect_obj = inspect_sym = null; + return; + } var val = gen[name]; if (val === undefined && current_output.code) { - var re = new RegExp("(\\w+__DOT__" + name + ")\\b", "gm"); + var re = new RegExp("(\\w+__DOT__(?:_[dcw]_)" + name + ")\\b", "gm"); var m = re.exec(current_output.code); if (m) { name = m[1]; diff --git a/src/worker/fs/fsSilice.data b/src/worker/fs/fsSilice.data new file mode 100644 index 00000000..b5836f50 --- /dev/null +++ b/src/worker/fs/fsSilice.data @@ -0,0 +1,6952 @@ +module M_%MODULE%_mem_%NAME%( +input [%WENABLE0_WIDTH%:0] in_%NAME%_wenable0, +input %DATA_TYPE% [%DATA_WIDTH%:0] in_%NAME%_wdata0, +input [%ADDR0_WIDTH%:0] in_%NAME%_addr0, +input [%WENABLE1_WIDTH%:0] in_%NAME%_wenable1, +input [%DATA_WIDTH%:0] in_%NAME%_wdata1, +input [%ADDR1_WIDTH%:0] in_%NAME%_addr1, +output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata0, +output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata1, +input %CLOCK%0, +input %CLOCK%1 +); +reg %DATA_TYPE% [%DATA_WIDTH%:0] buffer[%DATA_SIZE%:0]; +always @(posedge %CLOCK%0) begin + out_%NAME%_rdata0 <= buffer[in_%NAME%_addr0]; + if (in_%NAME%_wenable0) begin + out_%NAME%_rdata0 <= in_%NAME%_wdata0; + buffer[in_%NAME%_addr0] <= in_%NAME%_wdata0; + end +end +always @(posedge %CLOCK%1) begin + out_%NAME%_rdata1 <= buffer[in_%NAME%_addr1]; + if (in_%NAME%_wenable1) begin + out_%NAME%_rdata1 <= in_%NAME%_wdata1; + buffer[in_%NAME%_addr1] <= in_%NAME%_wdata1; + end +end +%INITIAL% +endmodule +module M_%MODULE%_mem_%NAME%( +input [%WENABLE_WIDTH%:0] in_%NAME%_wenable, +input %DATA_TYPE% [%DATA_WIDTH%:0] in_%NAME%_wdata, +input [%ADDR_WIDTH%:0] in_%NAME%_addr, +output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata, +input %CLOCK% +); +reg %DATA_TYPE% [%DATA_WIDTH%:0] buffer[%DATA_SIZE%:0]; +always @(posedge %CLOCK%) begin + if (in_%NAME%_wenable) begin + buffer[in_%NAME%_addr] <= in_%NAME%_wdata; + end + out_%NAME%_rdata <= buffer[in_%NAME%_addr]; +end +%INITIAL% +endmodule +module M_%MODULE%_mem_%NAME%( +input [%WENABLE0_WIDTH%:0] in_%NAME%_wenable0, +input %DATA_TYPE% [%DATA_WIDTH%:0] in_%NAME%_wdata0, +input [%ADDR0_WIDTH%:0] in_%NAME%_addr0, +input [%WENABLE1_WIDTH%:0] in_%NAME%_wenable1, +input [%DATA_WIDTH%:0] in_%NAME%_wdata1, +input [%ADDR1_WIDTH%:0] in_%NAME%_addr1, +output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata0, +output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata1, +input %CLOCK%0, +input %CLOCK%1 +); +reg %DATA_TYPE% [%DATA_WIDTH%:0] buffer[%DATA_SIZE%:0]; +always @(posedge %CLOCK%0) begin + if (in_%NAME%_wenable0) begin + buffer[in_%NAME%_addr0] <= in_%NAME%_wdata0; + end else begin + out_%NAME%_rdata0 <= buffer[in_%NAME%_addr0]; + end +end +always @(posedge %CLOCK%1) begin + if (in_%NAME%_wenable1) begin + buffer[in_%NAME%_addr1] <= in_%NAME%_wdata1; + end else begin + out_%NAME%_rdata1 <= buffer[in_%NAME%_addr1]; + end +end +%INITIAL% +endmodule +module M_%MODULE%_mem_%NAME%( +input [%ADDR0_WIDTH%:0] in_%NAME%_addr0, +output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata0, +output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata1, +input [%WENABLE1_WIDTH%:0] in_%NAME%_wenable1, +input [%DATA_WIDTH%:0] in_%NAME%_wdata1, +input [%ADDR1_WIDTH%:0] in_%NAME%_addr1, +input %CLOCK%0, +input %CLOCK%1 +); +reg %DATA_TYPE% [%DATA_WIDTH%:0] buffer[%DATA_SIZE%:0]; +always @(posedge %CLOCK%0) begin + out_%NAME%_rdata0 <= buffer[in_%NAME%_addr0]; +end +always @(posedge %CLOCK%1) begin + if (in_%NAME%_wenable1) begin + buffer[in_%NAME%_addr1] <= in_%NAME%_wdata1; + end +end +%INITIAL% +endmodule +module M_%MODULE%_mem_%NAME%( +input [%ADDR_WIDTH%:0] in_%NAME%_addr, +output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata, +input %CLOCK% +); +reg %DATA_TYPE% [%DATA_WIDTH%:0] buffer[%DATA_SIZE%:0]; +always @(posedge %CLOCK%) begin + out_%NAME%_rdata <= buffer[in_%NAME%_addr]; +end +%INITIAL% +endmodule +// ----------------------- memory_ports.ice ----------- +// @sylefeb - Silice standard library +// Memory port interfaces +// 2020-09-03 + +// single port BRAM + +interface bram_port { + output! addr, + output! wenable, + input rdata, + output! wdata, +} + +// single port BROM + +interface brom_port { + output! addr, + input rdata, +} + +// dual port BRAM + +interface dualbram_port0 { + output! addr0, + output! wenable0, + input rdata0, + output! wdata0, +} + +interface dualbram_port1 { + output! addr1, + output! wenable1, + input rdata1, + output! wdata1, +} + +// simple dual port BRAM + +interface simple_dualbram_port0 { + output! addr0, + input rdata0, +} + +interface simple_dualbram_port1 { + output! addr1, + output! wenable1, + output! wdata1, +} + +interface bram_ports { + output! addr0, + output! wenable0, + input rdata0, + output! wdata0, + output! addr1, + output! wenable1, + input rdata1, + output! wdata1, +} + +// ----------------------- end of memory_ports.ice ---- +/* + + Silice FPGA language and compiler + (c) Sylvain Lefebvre - @sylefeb + +This work and all associated files are under the + + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + +A copy of the license full text is included in +the distribution, please refer to it for details. + +(header_1_0) +*/ +// Sylvain Lefebvre 2019-09-26 + +#include "VgaChip.h" +#include "video_out.h" + +VgaChip::VgaChip(int color_depth) +{ + m_VideoOut = new VideoOut( + 0/*debug*/,color_depth/*color depth*/,0/*polarity*/, + 640 ,16,96,48, + 480 ,10,2,33, + "vgaout"); +} + +VgaChip::~VgaChip() +{ + delete (m_VideoOut); +} + +void VgaChip::eval( + vluint8_t clk, + vluint8_t vs, + vluint8_t hs, + vluint8_t red, + vluint8_t green, + vluint8_t blue) +{ + m_VideoOut->eval_RGB_HV(clk,vs,hs,red,green,blue); +} + +/* + + Silice FPGA language and compiler + (c) Sylvain Lefebvre - @sylefeb + +This work and all associated files are under the + + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + +A copy of the license full text is included in +the distribution, please refer to it for details. + +(header_1_0) +*/ +// +// Based on code from the MCC216 project (https://github.com/fredrequin/fpga_1943) +// (c) Frederic Requin, GPL v3 license +// + +#include "verilated.h" +#include "video_out.h" +#include "LibSL/Image/Image.h" +#include "LibSL/Image/ImageFormat_TGA.h" +#include "LibSL/Math/Vertex.h" +#include +#include +#include + +using namespace LibSL::Image; +using namespace LibSL::Math; + +ImageFormat_TGA g_RegisterFormat_TGA; + +// Constructor +VideoOut::VideoOut(vluint8_t debug, vluint8_t depth, vluint8_t polarity, + vluint16_t hactive, vluint16_t hfporch_, vluint16_t hspulse_, vluint16_t hbporch_, + vluint16_t vactive, vluint16_t vfporch_, vluint16_t vspulse_, vluint16_t vbporch_, + const char *file) +{ + // color depth + if (depth <= 8) { + bit_mask = (1 << depth) - 1; + bit_shift = (int)(8 - depth); + } else { + bit_mask = (vluint8_t)0xFF; + bit_shift = (int)0; + } + // synchros polarities + hs_pol = (polarity & HS_POS_POL) ? (vluint8_t)1 : (vluint8_t)0; + vs_pol = (polarity & VS_POS_POL) ? (vluint8_t)1 : (vluint8_t)0; + // screen format initialized + hor_size = hactive; + ver_size = vactive; + // record synch values + hfporch = hfporch_; + hspulse = hspulse_; + hbporch = hbporch_; + vfporch = vfporch_; + vspulse = vspulse_; + vbporch = vbporch_; + // debug mode + dbg_on = debug; + // allocate the pixels + std::cerr << hactive << " x " << vactive << " x " << (int)depth << std::endl; + pixels.allocate((int)hactive, (int)vactive); + // copy the filename + filename = std::string(file); + // internal variables cleared + hcount = (vluint16_t)hor_size; + vcount = (vluint16_t)ver_size; + prev_clk = (vluint8_t)0; + prev_hs = (vluint8_t)0; + prev_vs = (vluint8_t)0; + dump_ctr = (int)0; + // synch + v_sync_stage = e_Front; + h_sync_stage = e_Front; + v_sync_count = 0; + h_sync_count = 0; +} + +// Destructor +VideoOut::~VideoOut() +{ + +} + +// evaluate : RGB with synchros +void VideoOut::eval_RGB_HV +( + // Clock + vluint8_t clk, + // Synchros + vluint8_t vs, + vluint8_t hs, + // RGB colors + vluint8_t red, + vluint8_t green, + vluint8_t blue +) +{ + + // Rising edge on clock + if (clk && !prev_clk) { + //printf("\nh stage %d, v stage %d, hs %d (prev:%d), vs %d (prev:%d), hcount %d, vcount %d, hsync_cnt:%d, vsync_cnt:%d\n", + // h_sync_stage,v_sync_stage,hs,prev_hs,vs,prev_vs,hcount,vcount,h_sync_count,v_sync_count); + + // Horizontal synch update + bool h_sync_achieved = false; + switch (h_sync_stage) + { + case e_Front: + h_sync_count ++; + if (h_sync_count == hfporch-1) { + h_sync_stage = e_SynchPulseUp; + h_sync_count = 0; + } + break; + case e_SynchPulseUp: + if ((hs == hs_pol) && (prev_hs != hs_pol)) { + // raising edge on hs + h_sync_stage = e_SynchPulseDown; + if (dbg_on) printf(" Rising edge on HS"); + } + break; + case e_SynchPulseDown: + if ((hs != hs_pol) && (prev_hs != hs_pol)) { + // falling edge on hs + h_sync_stage = e_Back; + h_sync_count ++; + } + break; + case e_Back: + h_sync_count ++; + if (h_sync_count == hbporch) { + h_sync_stage = e_Done; + h_sync_count = 0; + hcount = 0; + // just achived hsynch + h_sync_achieved = true; + // end of frame? + if (vcount >= ver_size) { + // yes, trigger vsynch + vcount = 0; + h_sync_stage = e_Front; + } + } + break; + case e_Done: break; + } + + // Vertical synch update, if horizontal synch achieved + if (h_sync_achieved) { + + switch (v_sync_stage) + { + case e_Front: + v_sync_count ++; + if (v_sync_count == vfporch-1) { + v_sync_stage = e_SynchPulseUp; + v_sync_count = 0; + } + break; + case e_SynchPulseUp: + if ((vs == vs_pol) && (prev_vs != vs_pol)) { + // raising edge on vs + v_sync_stage = e_SynchPulseDown; + if (dbg_on) printf(" Rising edge on VS"); + } + break; + case e_SynchPulseDown: + if ((vs != vs_pol) && (prev_vs != vs_pol)) { + // falling edge on vs + v_sync_stage = e_Back; + v_sync_count ++; + + } + break; + case e_Back: + v_sync_count ++; + if (v_sync_count == vbporch) { + vcount = 0; + v_sync_stage = e_Done; + v_sync_count = 0; + { + char num[64]; + snprintf(num,64, "%04d", dump_ctr); + std::string tmp = filename + "_" + std::string(num) + ".tga"; + // printf(" Save snapshot in file \"%s\"\n", tmp.c_str()); + { + ImageRGB img; + img.pixels() = pixels; + saveImage(tmp.c_str(),&img); + } + dump_ctr++; + } + } + break; + case e_Done: break; + } + + prev_vs = vs; + + } + + // reset horizontal synchro + if (h_sync_stage == e_Done) { + if (hcount >= hor_size) { + h_sync_stage = e_Front; + vcount ++; + } + } + // reset vertical synchro + if (v_sync_stage == e_Done) { + if (vcount >= ver_size) { + h_sync_stage = e_Front; + v_sync_stage = e_Front; + } + } + + // Grab active area + if (v_sync_stage == e_Done && h_sync_stage == e_Done) { + + if (vcount < ver_size) { + if (hcount < hor_size) { + + uchar r = (red & bit_mask) << (bit_shift); + uchar g = (green & bit_mask) << (bit_shift); + uchar b = (blue & bit_mask) << (bit_shift); + + if (hcount >= 0 && vcount >= 0 && hcount < pixels.xsize() && vcount < pixels.ysize()) { + pixels.at((int)(hcount), (int)(vcount)) = v3b(r,g,b); + // printf("*** [pixel write at %d,%d R%dG%dB%d]\n",hcount,vcount,(int)r,(int)g,(int)b); + } else { + printf("*** [ERROR] out of bounds pixel write at %d,%d R%dG%dB%d]\n",hcount,vcount,(int)r,(int)g,(int)b); + } + } + } + } + + hcount ++; + + prev_hs = hs; + + } + + prev_clk = clk; + +} + +vluint16_t VideoOut::get_hcount() +{ + return hcount; +} + +vluint16_t VideoOut::get_vcount() +{ + return vcount; +} + +/* + + Silice FPGA language and compiler + (c) Sylvain Lefebvre - @sylefeb + +This work and all associated files are under the + + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + +A copy of the license full text is included in +the distribution, please refer to it for details. + +(header_1_0) +*/ +// SL 2019-10-09 + +#include "Vtop.h" +#include + +int main(int argc,char **argv) +{ + + Verilated::commandArgs(argc,argv); + + Vtop *bare_test = new Vtop(); + + char foo[1<<17]; // DEBUG FIXME: there is an access violation that makes this necessary. I have not been able to track it down so far!! Terrible. + + while (!Verilated::gotFinish()) { + + bare_test->clk = 1; + + bare_test->eval(); + + bare_test->clk = 0; + + bare_test->eval(); + + } + + return 0; +} + +/* + + Silice FPGA language and compiler + (c) Sylvain Lefebvre - @sylefeb + +This work and all associated files are under the + + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + +A copy of the license full text is included in +the distribution, please refer to it for details. + +(header_1_0) +*/ +// SL 2019-09-23 + +#include "Vtop.h" +#include + +#include "VgaChip.h" +#include "sdr_sdram.h" + +unsigned int main_time = 0; +double sc_time_stamp() +{ + return main_time; +} + +int main(int argc,char **argv) +{ + Verilated::commandArgs(argc,argv); + + Vtop *vga_test = new Vtop(); + + vga_test->clk = 0; + + // we need to step simulation until we get the parameters + do { + + vga_test->clk = 1 - vga_test->clk; + + vga_test->eval(); + + } while ((int)vga_test->video_color_depth == 0); + + VgaChip *vga_chip = new VgaChip((int)vga_test->video_color_depth); + + char foo[1<<18]; // DEBUG FIXME: there is an access violation that makes this necessary. I have not been able to track it down so far!! Terrible. + + vluint8_t sdram_flags = 0; + if ((int)vga_test->sdram_word_width == 8) { + sdram_flags |= FLAG_DATA_WIDTH_8; + } else if ((int)vga_test->sdram_word_width == 16) { + sdram_flags |= FLAG_DATA_WIDTH_16; + } else if ((int)vga_test->sdram_word_width == 32) { + sdram_flags |= FLAG_DATA_WIDTH_32; + } else if ((int)vga_test->sdram_word_width == 64) { + sdram_flags |= FLAG_DATA_WIDTH_64; + } + + SDRAM* sdr = new SDRAM(13 /*8192*/, 10 /*1024*/, sdram_flags, NULL); + // "sdram.txt"); + vluint64_t sdram_dq = 0; + + vluint8_t prev_vga_vs = 0; + + while (!Verilated::gotFinish()) { + + vga_test->clk = 1 - vga_test->clk; + + vga_test->eval(); + + sdr->eval(main_time, + vga_test->sdram_clock, 1, + vga_test->sdram_cs, vga_test->sdram_ras, vga_test->sdram_cas, vga_test->sdram_we, + vga_test->sdram_ba, vga_test->sdram_a, + vga_test->sdram_dqm, (vluint64_t)vga_test->sdram_dq_o, sdram_dq); + + vga_test->sdram_dq_i = (vga_test->sdram_dq_en) ? vga_test->sdram_dq_o : sdram_dq; + + if (prev_vga_vs == 0 && vga_test->video_vs != 0) { + static int cnt = 0; + char str[256]; + snprintf(str,256,"dump_%04d.raw",cnt++); + sdr->save(str,4*8192*1024*2,0); + } + prev_vga_vs = vga_test->video_vs; + + vga_chip->eval( + vga_test->video_clock, + vga_test->video_vs,vga_test->video_hs, + vga_test->video_r,vga_test->video_g,vga_test->video_b); + + main_time ++; + } + + return 0; +} + +// Copyright 2013 Frederic Requin +// +// This file is part of the MCC216 project (www.arcaderetrogaming.com) +// +// The SDRAM C++ model is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// The SDRAM C++ model is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// SDRAM C++ model: +// ---------------- +// - Based on the verilog model from Micron : "mt48lc8m16a2.v" // 2 meg x 16 x 4 banks +// - Designed to work with "Verilator" tool (www.veripool.org) +// - 8/16/32-bit data bus supported +// - 4 banks only +// - Two memory layouts : interleaved banks or contiguous banks +// - Sequential burst only, no interleaved burst yet +// - Binary images can be loaded to and saved from SDRAM +// - Debug mode to trace every SDRAM access +// - Endianness support for 16 and 32-bit memories +// +// TODO: +// - Add interleaved burst support +// +// 2020-03-03 - included in silice project, Sylvain Lefebvre, @sylefeb + +#ifndef _SDR_SDRAM_H_ +#define _SDR_SDRAM_H_ + +#include "verilated.h" + +#define SDRAM_NUM_BANKS (4) +#define SDRAM_BIT_BANKS (2) +#define CMD_PIPE_DEPTH (4) +#define DQM_PIPE_DEPTH (2) + +#define FLAG_DATA_WIDTH_8 ((vluint8_t)0x00) +#define FLAG_DATA_WIDTH_16 ((vluint8_t)0x01) +#define FLAG_DATA_WIDTH_32 ((vluint8_t)0x03) +#define FLAG_DATA_WIDTH_64 ((vluint8_t)0x07) +#define FLAG_BANK_INTERLEAVING ((vluint8_t)0x08) +#define FLAG_BIG_ENDIAN ((vluint8_t)0x10) +#define FLAG_RANDOM_FILLED ((vluint8_t)0x20) +#define FLAG_DEBUG_ON ((vluint8_t)0x40) + +class SDRAM +{ + public: + // Constructor and destructor + SDRAM(vluint8_t log2_rows, vluint8_t log2_cols, vluint8_t flags, char *logfile); + ~SDRAM(); + // Methods + void load(const char *name, vluint32_t size, vluint32_t addr); + void save(const char *name, vluint32_t size, vluint32_t addr); + void eval(vluint64_t ts, vluint8_t clk, vluint8_t cke, + vluint8_t cs_n, vluint8_t ras_n, vluint8_t cas_n, vluint8_t we_n, + vluint8_t ba, vluint16_t addr, + vluint8_t dqm, vluint64_t dq_in, vluint64_t &dq_out); + vluint8_t read_byte(vluint32_t addr); + vluint16_t read_word(vluint32_t addr); + vluint32_t read_long(vluint32_t addr); + vluint64_t read_quad(vluint32_t addr); + vluint32_t mem_size; + private: + // Byte reading functions (to speedup access) + vluint8_t (SDRAM::*read_byte_priv)(vluint32_t); + vluint8_t read_byte_i_be_8(vluint32_t addr); + vluint8_t read_byte_i_be_16(vluint32_t addr); + vluint8_t read_byte_i_be_32(vluint32_t addr); + vluint8_t read_byte_i_be_64(vluint32_t addr); + vluint8_t read_byte_i_le_8(vluint32_t addr); + vluint8_t read_byte_i_le_16(vluint32_t addr); + vluint8_t read_byte_i_le_32(vluint32_t addr); + vluint8_t read_byte_i_le_64(vluint32_t addr); + vluint8_t read_byte_c_be_8(vluint32_t addr); + vluint8_t read_byte_c_be_16(vluint32_t addr); + vluint8_t read_byte_c_be_32(vluint32_t addr); + vluint8_t read_byte_c_be_64(vluint32_t addr); + vluint8_t read_byte_c_le_8(vluint32_t addr); + vluint8_t read_byte_c_le_16(vluint32_t addr); + vluint8_t read_byte_c_le_32(vluint32_t addr); + vluint8_t read_byte_c_le_64(vluint32_t addr); + // SDRAM capacity + int bus_mask; // Data bus width (bytes - 1) + int bus_log2; // Data bus width (log2(bytes)) + int num_rows; // Number of rows + int num_cols; // Number of columns + int bit_rows; // Number of rows (log 2) + int bit_cols; // Number of columns (log 2) + vluint32_t mask_bank; // Bit mask for banks + vluint32_t mask_rows; // Bit mask for rows + vluint32_t mask_cols; // Bit mask for columns + // Memory arrays + vluint8_t *mem_array_7[SDRAM_NUM_BANKS]; // MSB + vluint8_t *mem_array_6[SDRAM_NUM_BANKS]; + vluint8_t *mem_array_5[SDRAM_NUM_BANKS]; + vluint8_t *mem_array_4[SDRAM_NUM_BANKS]; + vluint8_t *mem_array_3[SDRAM_NUM_BANKS]; + vluint8_t *mem_array_2[SDRAM_NUM_BANKS]; + vluint8_t *mem_array_1[SDRAM_NUM_BANKS]; + vluint8_t *mem_array_0[SDRAM_NUM_BANKS]; // LSB + // Mode register + int cas_lat; // CAS latency (2 or 3) + int bst_len_rd; // Burst length during read + int bst_len_wr; // Burst length during write + vluint8_t bst_type; // Burst type + // Debug mode + vluint8_t dbg_on; + // Special memory flags + vluint8_t mem_flags; + // Internal variables + vluint8_t prev_clk; // Previous clock state + vluint8_t cmd_pipe[CMD_PIPE_DEPTH]; // Command pipeline + int col_pipe[CMD_PIPE_DEPTH]; // Column address pipeline + vluint8_t ba_pipe[CMD_PIPE_DEPTH]; // Bank address pipeline + vluint8_t bap_pipe[CMD_PIPE_DEPTH]; // Bank precharge pipeline + vluint8_t a10_pipe[CMD_PIPE_DEPTH]; // A[10] wire pipeline + vluint8_t dqm_pipe[DQM_PIPE_DEPTH]; // DQM pipeline (for read) + vluint8_t row_act[SDRAM_NUM_BANKS]; // Bank activate + vluint8_t row_pre[SDRAM_NUM_BANKS]; // Bank precharge + int row_addr[SDRAM_NUM_BANKS]; // Row address during activate + vluint8_t ap_bank[SDRAM_NUM_BANKS]; // Bank being auto-precharged + int bank; // Current bank during read/write + int row; // Current row during read/write + int col; // Current column during read/write + int bst_ctr_rd; // Burst counter (read) + int bst_ctr_wr; // Burst counter (write) +public: + // Log file + FILE *fh_log; + char *log_buf; + int log_size; +}; + +#endif /* _SDR_SDRAM_H_ */ +// Copyright 2013 Frederic Requin +// +// This file is part of the MCC216 project (www.arcaderetrogaming.com) +// +// The SDRAM C++ model is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// The SDRAM C++ model is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// SDRAM C++ model: +// ---------------- +// - Based on the verilog model from Micron : "mt48lc8m16a2.v" +// - Designed to work with "Verilator" tool (www.veripool.org) +// - 8/16/32-bit data bus supported +// - 4 banks only +// - Two memory layouts : interleaved banks or contiguous banks +// - Sequential burst only, no interleaved burst yet +// - Binary images can be loaded to and saved from SDRAM +// - Debug mode to trace every SDRAM access +// - Endianness support for 16 and 32-bit memories +// +// TODO: +// - Add interleaved burst support + +#include "verilated.h" +#include "sdr_sdram.h" +#include +#include +#include + +#include + +// SDRAM commands +#define CMD_LMR ((vluint8_t)0) +#define CMD_REF ((vluint8_t)1) +#define CMD_PRE ((vluint8_t)2) +#define CMD_ACT ((vluint8_t)3) +#define CMD_WR ((vluint8_t)4) +#define CMD_RD ((vluint8_t)5) +#define CMD_BST ((vluint8_t)6) +#define CMD_NOP ((vluint8_t)7) + +// Data lanes +#define DATA_MSB ((vluint8_t)0x01) +#define DATA_MSW ((vluint8_t)0x02) +#define DATA_MSL ((vluint8_t)0x04) + +// Constructor +SDRAM::SDRAM(vluint8_t log2_rows, vluint8_t log2_cols, vluint8_t flags, char *logfile) +{ + // memory size + int s = (int)1 << (log2_rows + log2_cols); + // SDRAM capacity initialized + bus_mask = flags & (DATA_MSB | DATA_MSW | DATA_MSL); + bus_log2 = (flags & DATA_MSB) ? 1 : 0; + bus_log2 = (flags & DATA_MSW) ? 2 : bus_log2; + bus_log2 = (flags & DATA_MSL) ? 3 : bus_log2; + bit_rows = (int)log2_rows; + bit_cols = (int)log2_cols; + num_rows = (int)1 << log2_rows; + num_cols = (int)1 << log2_cols; + mask_cols = (num_cols - 1) << bus_log2; + if (flags & FLAG_BANK_INTERLEAVING) + { + // Banks are interleaved + mask_rows = (vluint32_t)(num_rows - 1) << (log2_cols + bus_log2 + SDRAM_BIT_BANKS); + mask_bank = (vluint32_t)(SDRAM_NUM_BANKS - 1) << (log2_cols + bus_log2 ); + } + else + { + // Banks are contiguous + mask_rows = (vluint32_t)(num_rows - 1) << (log2_cols + bus_log2 ); + mask_bank = (vluint32_t)(SDRAM_NUM_BANKS - 1) << (log2_cols + bus_log2 + SDRAM_BIT_BANKS); + } + mem_size = s << (bus_log2 + SDRAM_BIT_BANKS); + // Init message + std::cerr << "Instantiating " << (mem_size >> 20) << " MB SDRAM : " << SDRAM_NUM_BANKS << " banks x " << num_rows << " rows x " << num_cols << " cols x " << (8 << bus_log2) << " bits" << std::endl; + // byte reading function + switch (flags & (DATA_MSB | DATA_MSW | DATA_MSL | FLAG_BANK_INTERLEAVING | FLAG_BIG_ENDIAN)) + { + // Little endian, contiguous banks + case 0x00 : read_byte_priv = &SDRAM::read_byte_c_le_8; break; + case 0x01 : read_byte_priv = &SDRAM::read_byte_c_le_16; break; + case 0x02 : read_byte_priv = &SDRAM::read_byte_c_le_32; break; + case 0x03 : read_byte_priv = &SDRAM::read_byte_c_le_32; break; + case 0x04 : read_byte_priv = &SDRAM::read_byte_c_le_64; break; + case 0x05 : read_byte_priv = &SDRAM::read_byte_c_le_64; break; + case 0x06 : read_byte_priv = &SDRAM::read_byte_c_le_64; break; + case 0x07 : read_byte_priv = &SDRAM::read_byte_c_le_64; break; + // Little endian, interleaved banks + case 0x08 : read_byte_priv = &SDRAM::read_byte_i_le_8; break; + case 0x09 : read_byte_priv = &SDRAM::read_byte_i_le_16; break; + case 0x0A : read_byte_priv = &SDRAM::read_byte_i_le_32; break; + case 0x0B : read_byte_priv = &SDRAM::read_byte_i_le_32; break; + case 0x0C : read_byte_priv = &SDRAM::read_byte_i_le_64; break; + case 0x0D : read_byte_priv = &SDRAM::read_byte_i_le_64; break; + case 0x0E : read_byte_priv = &SDRAM::read_byte_i_le_64; break; + case 0x0F : read_byte_priv = &SDRAM::read_byte_i_le_64; break; + // Big endian, contiguous banks + case 0x10 : read_byte_priv = &SDRAM::read_byte_c_be_8; break; + case 0x11 : read_byte_priv = &SDRAM::read_byte_c_be_16; break; + case 0x12 : read_byte_priv = &SDRAM::read_byte_c_be_32; break; + case 0x13 : read_byte_priv = &SDRAM::read_byte_c_be_32; break; + case 0x14 : read_byte_priv = &SDRAM::read_byte_c_be_64; break; + case 0x15 : read_byte_priv = &SDRAM::read_byte_c_be_64; break; + case 0x16 : read_byte_priv = &SDRAM::read_byte_c_be_64; break; + case 0x17 : read_byte_priv = &SDRAM::read_byte_c_be_64; break; + // Big endian, interleaved banks + case 0x18 : read_byte_priv = &SDRAM::read_byte_i_be_8; break; + case 0x19 : read_byte_priv = &SDRAM::read_byte_i_be_16; break; + case 0x1A : read_byte_priv = &SDRAM::read_byte_i_be_32; break; + case 0x1B : read_byte_priv = &SDRAM::read_byte_i_be_32; break; + case 0x1C : read_byte_priv = &SDRAM::read_byte_i_be_64; break; + case 0x1D : read_byte_priv = &SDRAM::read_byte_i_be_64; break; + case 0x1E : read_byte_priv = &SDRAM::read_byte_i_be_64; break; + case 0x1F : read_byte_priv = &SDRAM::read_byte_i_be_64; break; + } + + // debug mode + if (logfile) + { + fh_log = fopen(logfile, "w"); + log_buf = new char[2048]; + log_size = 0; + if ((fh_log) && (log_buf)) + { + printf("SDRAM log file \"%s\" created\n", logfile); + dbg_on = 1; + } + else + { + dbg_on = 0; + } + } + else + { + fh_log = (FILE *)NULL; + log_buf = (char *)NULL; + log_size = 0; + dbg_on = 0; + } + + // special flags + mem_flags = flags; + + // mode register cleared + cas_lat = 0; + bst_len_rd = (int)0; + bst_len_wr = (int)0; + bst_type = (vluint8_t)0; + + // internal variables cleared + prev_clk = (vluint8_t)0; + for (int i = 0; i < CMD_PIPE_DEPTH; i++) + { + cmd_pipe[i] = CMD_NOP; + col_pipe[i] = (int)0; + ba_pipe[i] = (vluint8_t)0; + bap_pipe[i] = (vluint8_t)0; + a10_pipe[i] = (vluint16_t)0; + } + dqm_pipe[0] = (vluint8_t)0; + dqm_pipe[1] = (vluint8_t)0; + for (int i = 0; i < SDRAM_NUM_BANKS; i++) + { + row_act[i] = (vluint8_t)1; + row_pre[i] = (vluint8_t)0; + row_addr[i] = (int)0; + ap_bank[i] = (vluint8_t)0; + } + bank = (int)0; + row = (int)0; + col = (int)0; + bst_ctr_rd = (int)0; + bst_ctr_wr = (int)0; + + // one array per byte lane and per bank (up to 16 arrays) + for (int i = 0; i < SDRAM_NUM_BANKS; i++) + { + mem_array_0[i] = new vluint8_t[s]; + if (flags & DATA_MSB) mem_array_1[i] = new vluint8_t[s]; + if (flags & DATA_MSW) mem_array_2[i] = new vluint8_t[s]; + if (flags & DATA_MSW) mem_array_3[i] = new vluint8_t[s]; + if (flags & DATA_MSL) mem_array_4[i] = new vluint8_t[s]; + if (flags & DATA_MSL) mem_array_5[i] = new vluint8_t[s]; + if (flags & DATA_MSL) mem_array_6[i] = new vluint8_t[s]; + if (flags & DATA_MSL) mem_array_7[i] = new vluint8_t[s]; + } + + if (flags & FLAG_RANDOM_FILLED) + { + // fill the arrays with random numbers + srand (time (NULL)); + for (int i = 0; i < SDRAM_NUM_BANKS; i++) + { + for (int j = 0; j < s; j++) + { + mem_array_0[i][j] = (vluint8_t)rand() & 0xFF; + if (flags & DATA_MSB) mem_array_1[i][j] = (vluint8_t)rand() & 0xFF; + if (flags & DATA_MSW) mem_array_2[i][j] = (vluint8_t)rand() & 0xFF; + if (flags & DATA_MSW) mem_array_3[i][j] = (vluint8_t)rand() & 0xFF; + if (flags & DATA_MSL) mem_array_4[i][j] = (vluint8_t)rand() & 0xFF; + if (flags & DATA_MSL) mem_array_5[i][j] = (vluint8_t)rand() & 0xFF; + if (flags & DATA_MSL) mem_array_6[i][j] = (vluint8_t)rand() & 0xFF; + if (flags & DATA_MSL) mem_array_7[i][j] = (vluint8_t)rand() & 0xFF; + } + } + } + else + { + // clear the arrays + for (int i = 0; i < SDRAM_NUM_BANKS; i++) + { + for (int j = 0; j < s; j++) + { + mem_array_0[i][j] = (vluint8_t)0; + if (flags & DATA_MSB) mem_array_1[i][j] = (vluint8_t)0; + if (flags & DATA_MSW) mem_array_2[i][j] = (vluint8_t)0; + if (flags & DATA_MSW) mem_array_3[i][j] = (vluint8_t)0; + if (flags & DATA_MSL) mem_array_4[i][j] = (vluint8_t)0; + if (flags & DATA_MSL) mem_array_5[i][j] = (vluint8_t)0; + if (flags & DATA_MSL) mem_array_6[i][j] = (vluint8_t)0; + if (flags & DATA_MSL) mem_array_7[i][j] = (vluint8_t)0; + } + } + } +} + +// Destructor +SDRAM::~SDRAM() +{ + // free the memory + for (int i = 0; i < SDRAM_NUM_BANKS; i++) + { + delete[] mem_array_0[i]; + if (mem_flags & DATA_MSB) delete[] mem_array_1[i]; + if (mem_flags & DATA_MSW) delete[] mem_array_2[i]; + if (mem_flags & DATA_MSW) delete[] mem_array_3[i]; + if (mem_flags & DATA_MSL) delete[] mem_array_4[i]; + if (mem_flags & DATA_MSL) delete[] mem_array_5[i]; + if (mem_flags & DATA_MSL) delete[] mem_array_6[i]; + if (mem_flags & DATA_MSL) delete[] mem_array_7[i]; + } +} + +// Binary file loading +void SDRAM::load(const char *name, vluint32_t size, vluint32_t addr) +{ + FILE *fh; + + fh = fopen(name, "rb"); + if (fh) + { + int row_size; // Row size (num_cols * 1, 2 or 4) + vluint8_t *row_buf; // Row buffer + int row_pos; // Row position (0 to num_rows - 1) + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + // Row size computation based on data bus width + row_size = (int)1 << (bit_cols + bus_log2); + // Allocate one full row + row_buf = new vluint8_t[row_size]; + + // Row position + row_pos = (int)addr >> (bit_cols + bus_log2); + // Banks layout + if (mem_flags & FLAG_BANK_INTERLEAVING) + { + // Banks are interleaved + bank_nr = row_pos & (SDRAM_NUM_BANKS - 1); + row_pos = row_pos >> SDRAM_BIT_BANKS; + } + else + { + // Banks are contiguous + bank_nr = row_pos >> bit_rows; + row_pos = row_pos & (num_rows - 1); + } + idx = row_pos << bit_cols; + + printf("Starting row : %d, starting bank : %d\n", row_pos, bank_nr); + printf("Loading 0x%08lX bytes @ 0x%08lX from binary file \"%s\"...", size, addr, name); + for (int i = 0; i < (int)size; i += row_size) + { + // Read one full row from the binary file + fread((void *)row_buf, row_size, 1, fh); + + // Here, we take care of the endianness + if (mem_flags & FLAG_BIG_ENDIAN) + { + // MSB first (motorola's way) + for (int j = 0; j < row_size; ) + { + // Write MSL (if present) + if (mem_flags & DATA_MSL) + { + mem_array_7[bank_nr][idx] = row_buf[j++]; + mem_array_6[bank_nr][idx] = row_buf[j++]; + mem_array_5[bank_nr][idx] = row_buf[j++]; + mem_array_4[bank_nr][idx] = row_buf[j++]; + } + // Write MSW (if present) + if (mem_flags & DATA_MSW) + { + mem_array_3[bank_nr][idx] = row_buf[j++]; + mem_array_2[bank_nr][idx] = row_buf[j++]; + } + // Write MSB (if present) + if (mem_flags & DATA_MSB) + { + mem_array_1[bank_nr][idx] = row_buf[j++]; + } + // Write LSB + mem_array_0[bank_nr][idx] = row_buf[j++]; + // Next word + idx++; + } + } + else + { + // LSB first (intel's way) + for (int j = 0; j < row_size; ) + { + // Write LSB + mem_array_0[bank_nr][idx] = row_buf[j++]; + // Write MSB (if present) + if (mem_flags & DATA_MSB) + { + mem_array_1[bank_nr][idx] = row_buf[j++]; + } + // Write MSW (if present) + if (mem_flags & DATA_MSW) + { + mem_array_2[bank_nr][idx] = row_buf[j++]; + mem_array_3[bank_nr][idx] = row_buf[j++]; + } + // Write MSL (if present) + if (mem_flags & DATA_MSL) + { + mem_array_4[bank_nr][idx] = row_buf[j++]; + mem_array_5[bank_nr][idx] = row_buf[j++]; + mem_array_6[bank_nr][idx] = row_buf[j++]; + mem_array_7[bank_nr][idx] = row_buf[j++]; + } + // Next word + idx++; + } + } + + // Compute next row's address + if (mem_flags & FLAG_BANK_INTERLEAVING) + { + // Increment bank number + bank_nr = (bank_nr + 1) & (SDRAM_NUM_BANKS - 1); + + // Bank #3 -> bank #0 + if (!bank_nr) + { + row_pos ++; + if ((row_pos == (int)num_rows) && ((i + row_size) < (int)size)) + { + printf("Memory overflow while loading !!\n"); + return; + } + } + else + { + idx -= (int)num_cols; + } + } + else + { + // Increment row position + row_pos = (row_pos + 1) & ((int)num_rows - 1); + + // Last row in a bank + if (!row_pos) + { + idx = 0; + bank_nr++; + if ((bank_nr == SDRAM_NUM_BANKS) && ((i + row_size) < (int)size)) + { + printf("Memory overflow while loading !!\n"); + return; + } + } + } + } + printf("OK\n"); + + delete[] row_buf; + } + else + { + printf("Cannot load binary file \"%s\" !!\n", name); + } +} + +// Binary file saving +void SDRAM::save(const char *name, vluint32_t size, vluint32_t addr) +{ + FILE *fh; + + fh = fopen(name, "wb"); + if (fh) + { + int row_size; // Row size (num_cols * 1, 2 or 4) + vluint8_t *row_buf; // Row buffer + int row_pos; // Row position (0 to num_rows - 1) + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + // Row size computation based on data bus width + row_size = (int)1 << (bit_cols + bus_log2); + // Allocate one full row + row_buf = new vluint8_t[row_size]; + + // Row position + row_pos = (int)addr >> (bus_log2 + bit_cols); + // Banks layout + if (mem_flags & FLAG_BANK_INTERLEAVING) + { + // Banks are interleaved + bank_nr = row_pos & (SDRAM_NUM_BANKS - 1); + row_pos = row_pos >> SDRAM_BIT_BANKS; + } + else + { + // Banks are contiguous + bank_nr = row_pos >> bit_rows; + row_pos = row_pos & (num_rows - 1); + } + idx = row_pos << bit_cols; + + printf("Saving 0x%08lX bytes @ 0x%08lX to binary file \"%s\"...", size, addr, name); + for (int i = 0; i < (int)size; i += row_size) + { + // Here, we take care of the endianness + if (mem_flags & FLAG_BIG_ENDIAN) + { + // MSB first (motorola's way) + for (int j = 0; j < row_size; ) + { + // Read MSL (if present) + if (mem_flags & DATA_MSL) + { + row_buf[j++] = mem_array_7[bank_nr][idx]; + row_buf[j++] = mem_array_6[bank_nr][idx]; + row_buf[j++] = mem_array_5[bank_nr][idx]; + row_buf[j++] = mem_array_4[bank_nr][idx]; + } + // Read MSW (if present) + if (mem_flags & DATA_MSW) + { + row_buf[j++] = mem_array_3[bank_nr][idx]; + row_buf[j++] = mem_array_2[bank_nr][idx]; + } + // Read MSB (if present) + if (mem_flags & DATA_MSB) + { + row_buf[j++] = mem_array_1[bank_nr][idx]; + } + // Read LSB + row_buf[j++] = mem_array_0[bank_nr][idx]; + // Next word + idx++; + } + } + else + { + // LSB first (intel's way) + for (int j = 0; j < row_size; ) + { + // Read LSB + row_buf[j++] = mem_array_0[bank_nr][idx]; + // Read MSB (if present) + if (mem_flags & DATA_MSB) + { + row_buf[j++] = mem_array_1[bank_nr][idx]; + } + // Read MSW (if present) + if (mem_flags & DATA_MSW) + { + row_buf[j++] = mem_array_2[bank_nr][idx]; + row_buf[j++] = mem_array_3[bank_nr][idx]; + } + // Read MSL (if present) + if (mem_flags & DATA_MSL) + { + row_buf[j++] = mem_array_4[bank_nr][idx]; + row_buf[j++] = mem_array_5[bank_nr][idx]; + row_buf[j++] = mem_array_6[bank_nr][idx]; + row_buf[j++] = mem_array_7[bank_nr][idx]; + } + // Next word + idx++; + } + } + + // Compute next row's address + if (mem_flags & FLAG_BANK_INTERLEAVING) + { + // Increment bank number + bank_nr = (bank_nr + 1) & (SDRAM_NUM_BANKS - 1); + + // Bank #3 -> bank #0 + if (!bank_nr) + { + row_pos ++; + if ((row_pos == (int)num_rows) && ((i + row_size) < (int)size)) + { + printf("Memory overflow while saving !!\n"); + return; + } + } + else + { + idx -= (int)num_cols; + } + } + else + { + // Increment row position + row_pos = (row_pos + 1) & ((int)num_rows - 1); + + // Last row in a bank + if (!row_pos) + { + idx = 0; + bank_nr++; + if ((bank_nr == SDRAM_NUM_BANKS) && ((i + row_size) < (int)size)) + { + printf("Memory overflow while saving !!\n"); + return; + } + } + } + + // Write one full row to the binary file + fwrite((void *)row_buf, row_size, 1, fh); + } + printf("OK\n"); + + delete[] row_buf; + fclose(fh); + } + else + { + printf("Cannot save binary file \"%s\" !!\n", name); + } +} + +// Read a byte +vluint8_t SDRAM::read_byte(vluint32_t addr) +{ + return (this->*read_byte_priv)(addr); +} + +// Read a word +vluint16_t SDRAM::read_word(vluint32_t addr) +{ + if (mem_flags & FLAG_BIG_ENDIAN) + { + return ((vluint16_t)(this->*read_byte_priv)(addr ) << 8) | + (vluint16_t)(this->*read_byte_priv)(addr + 1); + } + else + { + return ((vluint16_t)(this->*read_byte_priv)(addr + 1) << 8) | + (vluint16_t)(this->*read_byte_priv)(addr ); + } +} + +// Read a long +vluint32_t SDRAM::read_long(vluint32_t addr) +{ + if (mem_flags & FLAG_BIG_ENDIAN) + { + return ((vluint32_t)(this->*read_byte_priv)(addr ) << 24) | + ((vluint32_t)(this->*read_byte_priv)(addr + 1) << 16) | + ((vluint32_t)(this->*read_byte_priv)(addr + 2) << 8) | + (vluint32_t)(this->*read_byte_priv)(addr + 3); + } + else + { + return ((vluint32_t)(this->*read_byte_priv)(addr + 3) << 24) | + ((vluint32_t)(this->*read_byte_priv)(addr + 2) << 16) | + ((vluint32_t)(this->*read_byte_priv)(addr + 1) << 8) | + (vluint32_t)(this->*read_byte_priv)(addr ); + } +} + +// Read a quad +vluint64_t SDRAM::read_quad(vluint32_t addr) +{ + if (mem_flags & FLAG_BIG_ENDIAN) + { + return ((vluint64_t)(this->*read_byte_priv)(addr ) << 56) | + ((vluint64_t)(this->*read_byte_priv)(addr + 1) << 48) | + ((vluint64_t)(this->*read_byte_priv)(addr + 1) << 40) | + ((vluint64_t)(this->*read_byte_priv)(addr + 1) << 32) | + ((vluint64_t)(this->*read_byte_priv)(addr + 1) << 24) | + ((vluint64_t)(this->*read_byte_priv)(addr + 1) << 16) | + ((vluint64_t)(this->*read_byte_priv)(addr + 2) << 8) | + (vluint64_t)(this->*read_byte_priv)(addr + 3); + } + else + { + return ((vluint64_t)(this->*read_byte_priv)(addr + 3) << 56) | + ((vluint64_t)(this->*read_byte_priv)(addr + 2) << 48) | + ((vluint64_t)(this->*read_byte_priv)(addr + 2) << 40) | + ((vluint64_t)(this->*read_byte_priv)(addr + 2) << 32) | + ((vluint64_t)(this->*read_byte_priv)(addr + 2) << 24) | + ((vluint64_t)(this->*read_byte_priv)(addr + 2) << 16) | + ((vluint64_t)(this->*read_byte_priv)(addr + 1) << 8) | + (vluint64_t)(this->*read_byte_priv)(addr ); + } +} + +// Cycle evaluate +void SDRAM::eval +( + vluint64_t ts, + // Clock + vluint8_t clk, + vluint8_t cke, + // Commands + vluint8_t cs_n, + vluint8_t ras_n, + vluint8_t cas_n, + vluint8_t we_n, + // Address + vluint8_t ba, + vluint16_t addr, + // Data + vluint8_t dqm, + vluint64_t dq_in, + vluint64_t &dq_out +) +{ + // Clock enabled + if (cke) + { + // Rising edge on clock + if (clk && !(prev_clk)) + { + vluint8_t cmd; + vluint8_t a10; + + // Decode SDRAM command + if (!cs_n) + cmd = (ras_n << 2) | (cas_n << 1) | we_n; + else + cmd = CMD_NOP; + + // A[10] wire + a10 = (vluint8_t)((addr >> 10) & 1); + // Mask out extra bits + ba &= (SDRAM_NUM_BANKS - 1); + + // Command pipeline + for (int i = 0; i < CMD_PIPE_DEPTH; i++) + { + if (i == (CMD_PIPE_DEPTH - 1)) + { + cmd_pipe[i] = CMD_NOP; + col_pipe[i] = (int)0; + ba_pipe[i] = (vluint8_t)0; + bap_pipe[i] = (vluint8_t)0; + a10_pipe[i] = (vluint16_t)0; + } + else + { + cmd_pipe[i] = cmd_pipe[i+1]; + col_pipe[i] = col_pipe[i+1]; + ba_pipe[i] = ba_pipe[i+1]; + bap_pipe[i] = bap_pipe[i+1]; + a10_pipe[i] = a10_pipe[i+1]; + } + } + + // DQM pipeline + dqm_pipe[0] = dqm_pipe[1]; + dqm_pipe[1] = dqm; + + // Process SDRAM command (immediate) + switch (cmd) + { + // 000 : Load mode register + case CMD_LMR: + { + if (dbg_on) + { + printf("Load Std Mode Register @ %llu ps\n", ts); + log_size += sprintf(log_buf + log_size, "Load Std Mode Register @ %llu ps\n", ts); + } + + // CAS latency + switch((addr >> 4) & 7) + { + case 2: + { + if (dbg_on) + { + printf("CAS latency = 2 cycles\n"); + log_size += sprintf(log_buf + log_size, "CAS latency = 2 cycles\n"); + } + cas_lat = (int)2; + break; + } + case 3: + { + if (dbg_on) + { + printf("CAS latency = 3 cycles\n"); + log_size += sprintf(log_buf + log_size, "CAS latency = 3 cycles\n"); + } + cas_lat = (int)3; + break; + } + default: + { + if (dbg_on) + { + printf("CAS latency = ???\n"); + log_size += sprintf(log_buf + log_size, "CAS latency = ???\n"); + } + cas_lat = (int)0; // This disables pipelined commands + } + } + + // Burst length + switch (addr & 7) + { + case 0: + { + if (dbg_on) + { + printf("Read burst length = 1 word\n"); + log_size += sprintf(log_buf + log_size, "Read burst length = 1 word\n"); + } + bst_len_rd = (int)1; + break; + } + case 1: + { + if (dbg_on) + { + printf("Read burst length = 2 words\n"); + log_size += sprintf(log_buf + log_size, "Read burst length = 2 words\n"); + } + bst_len_rd = (int)2; + break; + } + case 2: + { + if (dbg_on) + { + printf("Read burst length = 4 words\n"); + log_size += sprintf(log_buf + log_size, "Read burst length = 4 words\n"); + } + bst_len_rd = (int)4; + break; + } + case 3: + { + if (dbg_on) + { + printf("Read burst length = 8 words\n"); + log_size += sprintf(log_buf + log_size, "Read burst length = 8 words\n"); + } + bst_len_rd = (int)8; + break; + } + case 7: + { + if (dbg_on) + { + printf("Read burst length = continuous\n"); + log_size += sprintf(log_buf + log_size, "Read burst length = continuous\n"); + } + bst_len_rd = (int)num_cols; + break; + } + default: + { + if (dbg_on) + { + printf("Read burst length = ???\n"); + log_size += sprintf(log_buf + log_size, "Read burst length = ???\n"); + } + bst_len_rd = (int)0; // This will disable burst read + } + } + + // Burst type + if (addr & 8) + { + if (dbg_on) + { + printf("Burst type = interleaved (NOT SUPPORTED !)\n"); + log_size += sprintf(log_buf + log_size, "Burst type = interleaved (NOT SUPPORTED !)\n"); + } + bst_type = (vluint8_t)1; + } + else + { + if (dbg_on) + { + printf("Burst type = sequential\n"); + log_size += sprintf(log_buf + log_size, "Burst type = sequential\n"); + } + bst_type = (vluint8_t)0; + } + + // Write burst + if (addr & 0x200) + { + if (dbg_on) + { + printf("Write burst length = 1\n"); + log_size += sprintf(log_buf + log_size, "Write burst length = 1\n"); + } + bst_len_wr = (int)1; + } + else + { + if (dbg_on) + { + if (bst_len_rd) + { + if (bst_len_rd <= (int)8) + { + printf("Write burst length = %d word(s)\n", bst_len_rd); + log_size += sprintf(log_buf + log_size, "Write burst length = %d word(s)\n", bst_len_rd); + } + else + { + printf("Write burst length = continuous\n"); + log_size += sprintf(log_buf + log_size, "Write burst length = continuous\n"); + } + } + else + { + // This disables burst write + printf("Write burst length = ???\n"); + log_size += sprintf(log_buf + log_size, "Write burst length = ???\n"); + } + } + bst_len_wr = bst_len_rd; + } + break; + } + // 001 : Auto refresh + case CMD_REF: + { + if (dbg_on) + log_size += sprintf(log_buf + log_size, "Auto Refresh @ %llu ps\n", ts); + + for (int i = 0; i < SDRAM_NUM_BANKS; i++) + { + if (!row_pre[i]) + { + printf("ERROR @ %llu ps : All banks must be Precharge before Auto Refresh\n", ts); + break; + } + } + break; + } + // 010 : Precharge + case CMD_PRE: + { + if (a10) + { + if (dbg_on) + log_size += sprintf(log_buf + log_size, "Precharge all banks @ %llu ps\n", ts); + + if (ap_bank[0] || ap_bank[1] || ap_bank[2] || ap_bank[3]) + { + printf("ERROR @ %llu ps : at least one bank is auto-precharged !\n", ts); + break; + } + + // Precharge all banks + for (int i = 0; i < SDRAM_NUM_BANKS; i++) + { + row_act[i] = 0; + row_pre[i] = 1; + } + } + else + { + if (dbg_on) + log_size += sprintf(log_buf + log_size, "Precharge bank #%d @ %llu ps\n", ba, ts); + + if (ap_bank[ba]) + { + printf("ERROR @ %llu ps : cannot apply a precharge to auto-precharged bank %d !\n", ts, ba); + break; + } + + // Precharge one bank + row_act[ba] = 0; + row_pre[ba] = 1; + } + + // Terminate a WRITE immediately + if ((a10) || (bank == (int)ba)) + bst_ctr_wr = 0; + + // CAS latency pipeline for READ + if (cas_lat) + { + cmd_pipe[cas_lat] = CMD_PRE; + bap_pipe[cas_lat] = ba; + a10_pipe[cas_lat] = a10; + } + + break; + } + // 011 : Activate + case CMD_ACT: + { + // Mask out extra bits + addr &= (num_rows - 1); + + if (dbg_on) + log_size += sprintf(log_buf + log_size, "Activate bank #%d, row #%d @ %llu ps\n", ba, addr, ts); + + if (row_act[ba]) + { + printf("ERROR @ %llu ps : bank %d already active !\n", ts, ba); + break; + } + + row_act[ba] = 1; + row_pre[ba] = 0; + row_addr[ba] = (int)addr << bit_cols; + + break; + } + // 100 : Write + case CMD_WR: + { + // Mask out extra bits + addr &= (mask_cols >> bus_log2); + + if (dbg_on) + log_size += sprintf(log_buf + log_size, "Write bank #%d, col #%d @ %llu ps\n", ba, addr, ts); + + if (!row_act[ba]) + { + printf("ERROR @ %llu ps : bank %d is not activated for WRITE !\n", ts, ba); + break; + } + + // Latch command right away + cmd_pipe[0] = CMD_WR; + col_pipe[0] = (int)addr; + ba_pipe[0] = ba; + + // Auto-precharge + ap_bank[ba] = a10; + + break; + } + // 101 : Read + case CMD_RD: + { + // Mask out extra bits + addr &= (mask_cols >> bus_log2); + + if (dbg_on) + log_size += sprintf(log_buf + log_size, "Read bank #%d, col #%d @ %llu ps\n", ba, addr, ts); + + if (!row_act[ba]) + { + printf("ERROR @ %llu ps : bank %d is not activated for READ !\n", ts, ba); + break; + } + + // CAS latency pipeline + if (cas_lat) + { + cmd_pipe[cas_lat] = CMD_RD; + col_pipe[cas_lat] = (int)addr; + ba_pipe[cas_lat] = ba; + } + + // Auto-precharge + ap_bank[ba] = a10; + + break; + } + // 110 : Burst stop + case CMD_BST: + { + if (dbg_on) + log_size += sprintf(log_buf + log_size, "Burst Stop bank #%d @ %llu ps\n", ba, ts); + + if (ap_bank[ba]) + { + printf("ERROR @ %llu ps : cannot apply a burst stop to auto-precharged bank %d !\n", ts, ba); + break; + } + + // Terminate a WRITE immediately + bst_ctr_wr = (vluint16_t)0; + + // CAS latency for READ + if (cas_lat) + { + cmd_pipe[cas_lat] = CMD_BST; + } + break; + } + // 111 : No operation + default: ; + } + + // Process SDRAM command (pipelined) + switch (cmd_pipe[0]) + { + // 010 : Precharge + case CMD_PRE: + { + if ((a10_pipe[0]) || (bap_pipe[0] == (vluint8_t)bank)) + bst_ctr_rd = (int)0; + break; + } + // 100 : Write + case CMD_WR: + { + // Bank, row and column addresses in memory array + bank = (int)ba_pipe[0]; + row = row_addr[bank] + (col_pipe[0] & ~(bst_len_wr - 1)); + col = col_pipe[0] & (bst_len_wr - 1); + bst_ctr_rd = (int)0; + bst_ctr_wr = bst_len_wr; + + if (dbg_on) + { + if (mem_flags & FLAG_BANK_INTERLEAVING) + fprintf(fh_log, "%08X : ", ((row_addr[bank] << SDRAM_BIT_BANKS) + (bank << bit_cols) + col_pipe[0]) << bus_log2); + else + fprintf(fh_log, "%08X : ", (row_addr[bank] + (bank << (bit_rows + bit_cols)) + col_pipe[0]) << bus_log2); + } + + break; + } + // 101 : Read + case CMD_RD: + { + if (dbg_on) + { + if (bst_ctr_rd) fprintf(fh_log, "\n"); + if (log_size) fprintf(fh_log, log_buf); + log_size = 0; + } + + // Bank, row and column addresses in memory array + bank = (int)ba_pipe[0]; + row = row_addr[bank] + (col_pipe[0] & ~(bst_len_rd - 1)); + col = col_pipe[0] & (bst_len_rd - 1); + bst_ctr_rd = bst_len_rd; + bst_ctr_wr = (int)0; + + if (dbg_on) + { + if (mem_flags & FLAG_BANK_INTERLEAVING) + fprintf(fh_log, "%08X : ", ((row_addr[bank] << SDRAM_BIT_BANKS) + (bank << bit_cols) + col_pipe[0]) << bus_log2); + else + fprintf(fh_log, "%08X : ", (row_addr[bank] + (bank << (bit_rows + bit_cols)) + col_pipe[0]) << bus_log2); + } + + break; + } + // 110 : Burst stop + case CMD_BST: + { + bst_ctr_rd = (int)0; + break; + } + // 111 : No operation + default: ; + } + + // Write to memory + if (bst_ctr_wr) + { + // Write MSL (if present) + if (mem_flags & DATA_MSL) + { + if (dqm & 0x80) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + mem_array_7[bank][row + col] = (vluint8_t)(dq_in >> 56); + if (dbg_on) fprintf(fh_log, "%02X", mem_array_7[bank][row + col]); + } + if (dqm & 0x40) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + mem_array_6[bank][row + col] = (vluint8_t)(dq_in >> 48); + if (dbg_on) fprintf(fh_log, "%02X", mem_array_6[bank][row + col]); + } + if (dqm & 0x20) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + mem_array_5[bank][row + col] = (vluint8_t)(dq_in >> 40); + if (dbg_on) fprintf(fh_log, "%02X", mem_array_5[bank][row + col]); + } + if (dqm & 0x10) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + mem_array_4[bank][row + col] = (vluint8_t)(dq_in >> 32); + if (dbg_on) fprintf(fh_log, "%02X", mem_array_4[bank][row + col]); + } + } + // Write MSW (if present) + if (mem_flags & DATA_MSW) + { + if (dqm & 0x08) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + mem_array_3[bank][row + col] = (vluint8_t)(dq_in >> 24); + if (dbg_on) fprintf(fh_log, "%02X", mem_array_3[bank][row + col]); + } + if (dqm & 0x04) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + mem_array_2[bank][row + col] = (vluint8_t)(dq_in >> 16); + if (dbg_on) fprintf(fh_log, "%02X", mem_array_2[bank][row + col]); + } + } + // Write MSB (if present) + if (mem_flags & DATA_MSB) + { + if (dqm & 0x02) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + mem_array_1[bank][row + col] = (vluint8_t)(dq_in >> 8); + if (dbg_on) fprintf(fh_log, "%02X", mem_array_1[bank][row + col]); + } + } + // Write LSB + if (dqm & 0x01) + { + if (dbg_on) fprintf(fh_log, "XX "); + } + else + { + mem_array_0[bank][row + col] = (vluint8_t)dq_in; + if (dbg_on) fprintf(fh_log, "%02X ", mem_array_0[bank][row + col]); + } + + // Burst counter (only sequential burst supported) + col = (col + 1) & (bst_len_wr - 1); + bst_ctr_wr--; + + // End of burst + if (bst_ctr_wr == (int)0) + { + // Auto-precharge case + if (ap_bank[bank]) + { + if (dbg_on) fprintf(fh_log, "PRE\n\n"); + ap_bank[bank] = (vluint8_t)0; + row_act[bank] = (vluint8_t)0; + row_pre[bank] = (vluint8_t)1; + } + else + { + if (dbg_on) fprintf(fh_log, "\n"); + } + if (log_size) + { + fprintf(fh_log, log_buf); + log_size = 0; + } + } + } + + // Read from memory + if (bst_ctr_rd) + { + vluint8_t dq_tmp[8]; + + dq_tmp[7] = (vluint8_t)0x00; + dq_tmp[6] = (vluint8_t)0x00; + dq_tmp[5] = (vluint8_t)0x00; + dq_tmp[4] = (vluint8_t)0x00; + dq_tmp[3] = (vluint8_t)0x00; + dq_tmp[2] = (vluint8_t)0x00; + dq_tmp[1] = (vluint8_t)0x00; + dq_tmp[0] = (vluint8_t)0x00; + + // Read MSL (if present) + if (mem_flags & DATA_MSL) + { + if (dqm_pipe[0] & 0x80) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + dq_tmp[7] = mem_array_7[bank][row + col]; + if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[7]); + } + if (dqm_pipe[0] & 0x40) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + dq_tmp[6] = mem_array_6[bank][row + col]; + if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[6]); + } + if (dqm_pipe[0] & 0x20) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + dq_tmp[5] = mem_array_5[bank][row + col]; + if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[5]); + } + if (dqm_pipe[0] & 0x10) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + dq_tmp[4] = mem_array_4[bank][row + col]; + if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[4]); + } + } + + // Read MSW (if present) + if (mem_flags & DATA_MSW) + { + if (dqm_pipe[0] & 0x08) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + dq_tmp[3] = mem_array_3[bank][row + col]; + if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[3]); + } + if (dqm_pipe[0] & 0x04) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + dq_tmp[2] = mem_array_2[bank][row + col]; + if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[2]); + } + } + + // Read MSB (if present) + if (mem_flags & DATA_MSB) + { + if (dqm_pipe[0] & 0x02) + { + if (dbg_on) fprintf(fh_log, "XX"); + } + else + { + dq_tmp[1] = mem_array_1[bank][row + col]; + if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[1]); + } + } + + // Read LSB + if (dqm_pipe[0] & 0x01) + { + if (dbg_on) fprintf(fh_log, "XX "); + } + else + { + dq_tmp[0] = mem_array_0[bank][row + col]; + if (dbg_on) fprintf(fh_log, "%02X ", dq_tmp[0]); + } + + dq_out = ((vluint64_t)dq_tmp[0] ) + | ((vluint64_t)dq_tmp[1] << 8 ) + | ((vluint64_t)dq_tmp[2] << 16) + | ((vluint64_t)dq_tmp[3] << 24) + | ((vluint64_t)dq_tmp[4] << 32) + | ((vluint64_t)dq_tmp[5] << 40) + | ((vluint64_t)dq_tmp[6] << 48) + | ((vluint64_t)dq_tmp[7] << 56); + + // Burst counter (only sequential supported) + col = (col + 1) & (bst_len_rd - 1); + bst_ctr_rd--; + + // End of burst + if (bst_ctr_rd == (int)0) + { + // Auto-precharge case + if (ap_bank[bank]) + { + if (dbg_on) fprintf(fh_log, "PRE\n"); + ap_bank[bank] = (vluint8_t)0; + row_act[bank] = (vluint8_t)0; + row_pre[bank] = (vluint8_t)1; + } + else + { + if (dbg_on) fprintf(fh_log, "\n"); + } + if (log_size) + { + fprintf(fh_log, log_buf); + log_size = 0; + } + } + } + } + + if ((bst_ctr_wr == (int)0) && (bst_ctr_rd == (int)0) && (log_size != (int)0)) + { + fprintf(fh_log, log_buf); + log_size = 0; + } + + // For edge detection + prev_clk = clk; + } + // Clock disabled + else + { + prev_clk = (vluint8_t)0; + } +} + +// Read a byte, interleaved banks, big endian, 8-bit SDRAM +vluint8_t SDRAM::read_byte_i_be_8(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> bit_cols; + idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)); + + return mem_array_0[bank_nr][idx]; +} + +// Read a byte, interleaved banks, big endian, 16-bit SDRAM +vluint8_t SDRAM::read_byte_i_be_16(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + 1); + idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 1; + + if (addr & 1) + return mem_array_0[bank_nr][idx]; + else + return mem_array_1[bank_nr][idx]; +} + +// Read a byte, interleaved banks, big endian, 32-bit SDRAM +vluint8_t SDRAM::read_byte_i_be_32(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + 2); + idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 2; + + switch (addr & 3) + { + case 0 : return mem_array_3[bank_nr][idx]; + case 1 : return mem_array_2[bank_nr][idx]; + case 2 : return mem_array_1[bank_nr][idx]; + case 3 : return mem_array_0[bank_nr][idx]; + } + return 0; +} + +// Read a byte, interleaved banks, big endian, 64-bit SDRAM +vluint8_t SDRAM::read_byte_i_be_64(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + 3); + idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 3; + + switch (addr & 7) + { + case 0 : return mem_array_7[bank_nr][idx]; + case 1 : return mem_array_6[bank_nr][idx]; + case 2 : return mem_array_5[bank_nr][idx]; + case 3 : return mem_array_4[bank_nr][idx]; + case 4 : return mem_array_3[bank_nr][idx]; + case 5 : return mem_array_2[bank_nr][idx]; + case 6 : return mem_array_1[bank_nr][idx]; + case 7 : return mem_array_0[bank_nr][idx]; + } + return 0; +} + +// Read a byte, interleaved banks, little endian, 8-bit SDRAM +vluint8_t SDRAM::read_byte_i_le_8(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> bit_cols; + idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)); + + return mem_array_0[bank_nr][idx]; +} + +// Read a byte, interleaved banks, little endian, 16-bit SDRAM +vluint8_t SDRAM::read_byte_i_le_16(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + 1); + idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 1; + + if (addr & 1) + return mem_array_1[bank_nr][idx]; + else + return mem_array_0[bank_nr][idx]; +} + +// Read a byte, interleaved banks, little endian, 32-bit SDRAM +vluint8_t SDRAM::read_byte_i_le_32(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + 2); + idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 2; + + switch (addr & 3) + { + case 0 : return mem_array_0[bank_nr][idx]; + case 1 : return mem_array_1[bank_nr][idx]; + case 2 : return mem_array_2[bank_nr][idx]; + case 3 : return mem_array_3[bank_nr][idx]; + } + return 0; +} + +// Read a byte, interleaved banks, little endian, 64-bit SDRAM +vluint8_t SDRAM::read_byte_i_le_64(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + 3); + idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 3; + + switch (addr & 7) + { + case 0 : return mem_array_0[bank_nr][idx]; + case 1 : return mem_array_1[bank_nr][idx]; + case 2 : return mem_array_2[bank_nr][idx]; + case 3 : return mem_array_3[bank_nr][idx]; + case 4 : return mem_array_4[bank_nr][idx]; + case 5 : return mem_array_5[bank_nr][idx]; + case 6 : return mem_array_6[bank_nr][idx]; + case 7 : return mem_array_7[bank_nr][idx]; + } + return 0; +} + +// Read a byte, contiguous banks, big endian, 8-bit SDRAM +vluint8_t SDRAM::read_byte_c_be_8(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows); + idx = (int)(addr & (mask_cols | mask_rows)); + + return mem_array_0[bank_nr][idx]; +} + +// Read a byte, contiguous banks, big endian, 16-bit SDRAM +vluint8_t SDRAM::read_byte_c_be_16(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 1); + idx = (int)(addr & (mask_cols | mask_rows)) >> 1; + + if (addr & 1) + return mem_array_0[bank_nr][idx]; + else + return mem_array_1[bank_nr][idx]; +} + +// Read a byte, contiguous banks, big endian, 32-bit SDRAM +vluint8_t SDRAM::read_byte_c_be_32(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 2); + idx = (int)(addr & (mask_cols | mask_rows)) >> 2; + + switch (addr & 3) + { + case 0 : return mem_array_3[bank_nr][idx]; + case 1 : return mem_array_2[bank_nr][idx]; + case 2 : return mem_array_1[bank_nr][idx]; + case 3 : return mem_array_0[bank_nr][idx]; + } + return 0; +} + +// Read a byte, contiguous banks, big endian, 64-bit SDRAM +vluint8_t SDRAM::read_byte_c_be_64(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 3); + idx = (int)(addr & (mask_cols | mask_rows)) >> 3; + + switch (addr & 7) + { + case 0 : return mem_array_7[bank_nr][idx]; + case 1 : return mem_array_6[bank_nr][idx]; + case 2 : return mem_array_5[bank_nr][idx]; + case 3 : return mem_array_4[bank_nr][idx]; + case 4 : return mem_array_3[bank_nr][idx]; + case 5 : return mem_array_2[bank_nr][idx]; + case 6 : return mem_array_1[bank_nr][idx]; + case 7 : return mem_array_0[bank_nr][idx]; + } + return 0; +} + +// Read a byte, contiguous banks, little endian, 8-bit SDRAM +vluint8_t SDRAM::read_byte_c_le_8(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows); + idx = (int)(addr & (mask_cols | mask_rows)); + + return mem_array_0[bank_nr][idx]; +} + +// Read a byte, contiguous banks, little endian, 16-bit SDRAM +vluint8_t SDRAM::read_byte_c_le_16(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 1); + idx = (int)(addr & (mask_cols | mask_rows)) >> 1; + + if (addr & 1) + return mem_array_1[bank_nr][idx]; + else + return mem_array_0[bank_nr][idx]; +} + +// Read a byte, contiguous banks, little endian, 32-bit SDRAM +vluint8_t SDRAM::read_byte_c_le_32(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 2); + idx = (int)(addr & (mask_cols | mask_rows)) >> 2; + + switch (addr & 3) + { + case 0 : return mem_array_0[bank_nr][idx]; + case 1 : return mem_array_1[bank_nr][idx]; + case 2 : return mem_array_2[bank_nr][idx]; + case 3 : return mem_array_3[bank_nr][idx]; + } + return 0; +} + +// Read a byte, contiguous banks, little endian, 64-bit SDRAM +vluint8_t SDRAM::read_byte_c_le_64(vluint32_t addr) +{ + int bank_nr; // Bank number (0 to 3) + int idx; // Array index (0 to num_cols * num_rows - 1) + + bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 3); + idx = (int)(addr & (mask_cols | mask_rows)) >> 3; + + switch (addr & 7) + { + case 0 : return mem_array_0[bank_nr][idx]; + case 1 : return mem_array_1[bank_nr][idx]; + case 2 : return mem_array_2[bank_nr][idx]; + case 3 : return mem_array_3[bank_nr][idx]; + case 4 : return mem_array_4[bank_nr][idx]; + case 5 : return mem_array_5[bank_nr][idx]; + case 6 : return mem_array_6[bank_nr][idx]; + case 7 : return mem_array_7[bank_nr][idx]; + } + return 0; +} +/* + + Silice FPGA language and compiler + (c) Sylvain Lefebvre - @sylefeb + +This work and all associated files are under the + + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + +A copy of the license full text is included in +the distribution, please refer to it for details. + +(header_1_0) +*/ +// Sylvain Lefebvre 2019-09-26 + +#pragma once + +#include "verilated.h" + +class VideoOut; + +/// \brief Isolates the implementation to simplify build +class VgaChip +{ +private: + + VideoOut *m_VideoOut = nullptr; + +public: + + VgaChip(int color_depth); + ~VgaChip(); + + void eval(vluint8_t clk, + vluint8_t vs, + vluint8_t hs, + vluint8_t red, + vluint8_t green, + vluint8_t blue); + +}; + +cmake_minimum_required(VERSION 2.6) +project(verilator_silice) + +# find_package(verilator) ? + +INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR}/ + ${PROJECT_SOURCE_DIR}/../../src/libs/LibSL-small/src + ${PROJECT_SOURCE_DIR}/../../src/libs/LibSL-small/src/LibSL + $ENV{VERILATOR_ROOT}/include +) + +add_definitions(-Wfatal-errors) + +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") +# hack to deal with https://github.com/verilator/verilator/issues/2502 +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +endif() + +ADD_LIBRARY(verilator_silice + video_out.cpp + video_out.h + sdr_sdram.cpp + sdr_sdram.h + VgaChip.cpp + VgaChip.h + ../../src/libs/LibSL-small/src/LibSL/System/System.cpp + ../../src/libs/LibSL-small/src/LibSL/CppHelpers/CppHelpers.cpp + ../../src/libs/LibSL-small/src/LibSL/StlHelpers/StlHelpers.cpp + ../../src/libs/LibSL-small/src/LibSL/Math/Math.cpp + ../../src/libs/LibSL-small/src/LibSL/Math/Vertex.cpp + ../../src/libs/LibSL-small/src/LibSL/Image/Image.cpp + ../../src/libs/LibSL-small/src/LibSL/Image/ImageFormat_TGA.cpp + ../../src/libs/LibSL-small/src/LibSL/Image/tga.cpp +) + +INSTALL(TARGETS verilator_silice ARCHIVE DESTINATION ${CMAKE_SOURCE_DIR}) + +/* + + Silice FPGA language and compiler + (c) Sylvain Lefebvre - @sylefeb + +This work and all associated files are under the + + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + +A copy of the license full text is included in +the distribution, please refer to it for details. + +(header_1_0) +*/ +// +// Implements VGA emulation for Verilator. +// Emulates front/back porch on horizontal and vertical synch. +// +// Based on code from the MCC216 project (https://github.com/fredrequin/fpga_1943) +// (c) Frederic Requin, GPL v3 license +// + +#pragma once + +#include "verilated.h" +#include "LibSL/Image/Image.h" + +#define HS_POS_POL 1 +#define HS_NEG_POL 0 +#define VS_POS_POL 2 +#define VS_NEG_POL 0 + +class VideoOut +{ + public: + + // Constructor and destructor + VideoOut( + vluint8_t debug, + vluint8_t depth, + vluint8_t polarity, + vluint16_t hactive, vluint16_t hfporch_, vluint16_t hspulse_, vluint16_t hbporch_, + vluint16_t vactive, vluint16_t vfporch_, vluint16_t vspulse_, vluint16_t vbporch_, + const char *file); + ~VideoOut(); + // Methods + void eval_RGB_HV(vluint8_t clk, vluint8_t vs, vluint8_t hs, vluint8_t red, vluint8_t green, vluint8_t blue); + vluint16_t get_hcount(); + vluint16_t get_vcount(); + private: + // Color depth + int bit_shift; + vluint8_t bit_mask; + // Synchros polarities + vluint8_t hs_pol; + vluint8_t vs_pol; + // Debug mode + vluint8_t dbg_on; + // H synch + vluint16_t hfporch; + vluint16_t hspulse; + vluint16_t hbporch; + // V synch + vluint16_t vfporch; + vluint16_t vspulse; + vluint16_t vbporch; + // Image format + vluint16_t hor_size; + vluint16_t ver_size; + // Pixel array + LibSL::Memory::Array::Array2D pixels; + // Image file name + std::string filename; + // Internal variable + vluint16_t hcount; + vluint16_t vcount; + vluint8_t prev_clk; + vluint8_t prev_hs; + vluint8_t prev_vs; + int dump_ctr; + + enum e_Synch {e_Front=0,e_SynchPulseUp=1,e_SynchPulseDown=2,e_Back=3,e_Done=4}; + + e_Synch v_sync_stage; + e_Synch h_sync_stage; + int v_sync_count; + int h_sync_count; +}; + +{ + "boards" : [ + { + "name" : "icarus" + }, + { + "name" : "verilator" + }, + { + "name" : "icebreaker" + }, + { + "name" : "icestick" + }, + { + "name" : "ulx3s" + }, + { + "name" : "de10nano" + }, + { + "name" : "orangecrab" + }, + { + "name" : "crosslink_nx_evn" + }, + { + "name" : "fomu" + }, + { + "name" : "mojov3" + }, + { + "name" : "techgraph" + }, + { + "name" : "8bitworkshop" + } + ] +} +#!/bin/bash + +case "$(uname -s)" in +MINGW*|CYGWIN*) +SILICE_DIR=`cygpath $SILICE_DIR` +BUILD_DIR=`cygpath $BUILD_DIR` +FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR` +FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE` +BOARD_DIR=`cygpath $BOARD_DIR` +;; +*) +esac + +echo "build script: SILICE_DIR = $SILICE_DIR" +echo "build script: BUILD_DIR = $BUILD_DIR" +echo "build script: BOARD_DIR = $BOARD_DIR" +echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR" +echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE" + +export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR +case "$(uname -s)" in +MINGW*) +export PYTHONHOME=/mingw64/bin +export PYTHONPATH=/mingw64/lib/python3.8/ +export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins +;; +*) +esac + +cd $BUILD_DIR + +rm build* + +silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}" + +yosys -q -p "synth_ice40 -json build.json" build.v +nextpnr-ice40 --up5k --freq 13 --package sg48 --json build.json --pcf $BOARD_DIR/icebreaker.pcf --asc build.asc + +icepack build.asc build.bin +iceprog build.bin +# ---------------------------------------------------------------------------- +# +# Icebreaker constraint file (.pcf) +# Pinout: +# https://github.com/icebreaker-fpga/icebreaker/blob/master/img/icebreaker-v1_0b-legend.jpg +# Link +# https://1bitsquared.com/collections/fpga/products/icebreaker +# +# ---------------------------------------------------------------------------- + +# -------------------------- SYSTEM CLOCK ------------------------------------ +set_io -nowarn CLK 35 + +# ------------------------------ UART ---------------------------------------- +set_io -nowarn RX 6 +set_io -nowarn TX 9 + +# ------------------------- LEDs and Button ---------------------------------- +set_io -nowarn BTN_N 10 +set_io -nowarn LEDR_N 11 +set_io -nowarn LEDG_N 37 + +# --------------------------- SPI Flash -------------------------------------- +set_io -nowarn FLASH_SCK 15 +set_io -nowarn FLASH_SSB 16 +set_io -nowarn FLASH_IO0 14 +set_io -nowarn FLASH_IO1 17 +set_io -nowarn FLASH_IO2 12 +set_io -nowarn FLASH_IO3 13 + +# ------------ Leds and Buttons (PMOD 2) ------------------------------------- +set_io -nowarn LED1 26 +set_io -nowarn LED2 27 +set_io -nowarn LED3 25 +set_io -nowarn LED4 23 +set_io -nowarn LED5 21 +set_io -nowarn BTN1 20 +set_io -nowarn BTN2 19 +set_io -nowarn BTN3 18 + +# ------------ PMOD1A connector ---------------------------------------------- +set_io -nowarn P1A1 4 +set_io -nowarn P1A2 2 +set_io -nowarn P1A3 47 +set_io -nowarn P1A4 45 +set_io -nowarn P1A7 3 +set_io -nowarn P1A8 48 +set_io -nowarn P1A9 46 +set_io -nowarn P1A10 44 + +# ------------ PMOD1B connector ---------------------------------------------- +set_io -nowarn P1B1 43 +set_io -nowarn P1B2 38 +set_io -nowarn P1B3 34 +set_io -nowarn P1B4 31 +set_io -nowarn P1B7 42 +set_io -nowarn P1B8 36 +set_io -nowarn P1B9 32 +set_io -nowarn P1B10 28 + +# ------------ Leds and Buttons (PMOD 2) ------------------------------------- +set_io -nowarn P2_1 27 +set_io -nowarn P2_2 25 +set_io -nowarn P2_3 21 +set_io -nowarn P2_4 19 +set_io -nowarn P2_7 26 +set_io -nowarn P2_8 23 +set_io -nowarn P2_9 20 +set_io -nowarn P2_10 18 +{ + "name": "icebreaker", + "variants": [ + { + "name" : "configurable", + "framework" : "icebreaker.v", + "pins" : [ + {"set" : "basic"}, + {"set" : "buttons", "define" : "BUTTONS=1"}, + {"set" : "uart", "define" : "UART=1"}, + {"set" : "vga", "define" : "VGA=1"} + ], + "builders": [ + { + "builder" : "edalize", + "description": "Build using Edalize", + "tool": "icestorm", + "tool_options": [ + { + "nextpnr_options": ["--up5k", "--freq 13", "--package sg48", "--timing-allow-fail"], + "pnr": "next" + } + ], + "bitstream" : "build.bin", + "constraints": [{"name": "icebreaker.pcf", "file_type": "PCF"}], + "program": [{"cmd" : "iceprog", "args" : "build.bin"}] + }, + { + "builder" : "shell", + "command" : "icebreaker.sh", + "description": "Custom shell scripts using yosys and nextpnr" + } + ] + } + ], + "pins": { + "basic": [ + { + "name": "leds", + "type": "uint5", + "io": "output" + } + ], + "buttons": [ + { + "name": "btns", + "type": "uint3", + "io": "input" + } + ], + "uart": [ + { + "name": "uart_tx", + "type": "uint1", + "io" : "output" + }, + { + "name": "uart_rx", + "type": "uint1", + "io" : "input" + } + ], + "vga": [ + { + "name": "vga_hs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_vs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_r", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_g", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_b", + "type": "uint6", + "io": "output" + } + ] + } +} +`define ICEBREAKER 1 +`default_nettype none +$$ICEBREAKER=1 +$$HARDWARE=1 +$$NUM_LEDS=5 +$$NUM_BTNS=3 +$$VGA=1 +$$color_depth=6 +$$color_max =63 +$$config['bram_wenable_width'] = 'data' +$$config['dualport_bram_wenable0_width'] = 'data' +$$config['dualport_bram_wenable1_width'] = 'data' + +module top( + output LED1, + output LED2, + output LED3, + output LED4, + output LED5, +`ifdef BUTTONS + input BTN1, + input BTN2, + input BTN3, +`endif +`ifdef UART + output TX, + input RX, +`endif +`ifdef VGA + output P1A1, // r0 + output P1A2, // r1 + output P1A3, // r2 + output P1A4, // r3 + + output P1A7, // b0 + output P1A8, // b1 + output P1A9, // b2 + output P1A10, // b3 + + output P1B1, // g0 + output P1B2, // g1 + output P1B3, // g2 + output P1B4, // g3 + + output P1B7, // hs + output P1B8, // vs +`endif + input CLK + ); + +wire [4:0] __main_leds; + +// clock from design is used in case +// it relies on a PLL: in such cases +// we cannot use the clock fed into +// the PLL here +wire design_clk; + +`ifdef VGA +wire __main_out_vga_hs; +wire __main_out_vga_vs; +wire __main_out_vga_v0; +wire [5:0] __main_out_vga_r; +wire [5:0] __main_out_vga_g; +wire [5:0] __main_out_vga_b; +`endif + +reg ready = 0; +reg [31:0] RST_d; +reg [31:0] RST_q; + +always @* begin + RST_d = RST_q >> 1; +end + +always @(posedge design_clk) begin + if (ready) begin + RST_q <= RST_d; + end else begin + ready <= 1; + RST_q <= 32'b111111111111111111111111111111; + end +end + +wire run_main; +assign run_main = 1'b1; + +M_main __main( + .clock(CLK), + .out_clock(design_clk), + .reset(RST_d[0]), + .out_leds(__main_leds), +`ifdef BUTTONS + .in_btns({BTN3,BTN2,BTN1}), +`endif +`ifdef UART + .out_uart_tx(TX), + .in_uart_rx(RX), +`endif +`ifdef VGA + .out_video_hs(__main_out_vga_hs), + .out_video_vs(__main_out_vga_vs), + .out_video_r(__main_out_vga_r), + .out_video_g(__main_out_vga_g), + .out_video_b(__main_out_vga_b), +`endif + .in_run(run_main) +); + +assign LED1 = __main_leds[0+:1]; +assign LED2 = __main_leds[1+:1]; +assign LED3 = __main_leds[2+:1]; +assign LED4 = __main_leds[3+:1]; +assign LED5 = __main_leds[4+:1]; + +`ifdef VGA +assign P1A1 = __main_out_vga_r[2+:1]; +assign P1A2 = __main_out_vga_r[3+:1]; +assign P1A3 = __main_out_vga_r[4+:1]; +assign P1A4 = __main_out_vga_r[5+:1]; + +assign P1A7 = __main_out_vga_b[2+:1]; +assign P1A8 = __main_out_vga_b[3+:1]; +assign P1A9 = __main_out_vga_b[4+:1]; +assign P1A10 = __main_out_vga_b[5+:1]; + +assign P1B1 = __main_out_vga_g[2+:1]; +assign P1B2 = __main_out_vga_g[3+:1]; +assign P1B3 = __main_out_vga_g[4+:1]; +assign P1B4 = __main_out_vga_g[5+:1]; + +assign P1B7 = __main_out_vga_hs; +assign P1B8 = __main_out_vga_vs; +`endif + +endmodule +#!/bin/bash + +case "$(uname -s)" in +MINGW*|CYGWIN*) +SILICE_DIR=`cygpath $SILICE_DIR` +BUILD_DIR=`cygpath $BUILD_DIR` +FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR` +FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE` +BOARD_DIR=`cygpath $BOARD_DIR` +;; +*) +esac + +echo "build script: SILICE_DIR = $SILICE_DIR" +echo "build script: BUILD_DIR = $BUILD_DIR" +echo "build script: BOARD_DIR = $BOARD_DIR" +echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR" +echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE" + +export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR +case "$(uname -s)" in +MINGW*) +export PYTHONHOME=/mingw64/bin +export PYTHONPATH=/mingw64/lib/python3.8/ +export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins +;; +*) +esac + +cd $BUILD_DIR + +rm build* + +silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}" + +yosys -p 'synth_ecp5 -abc9 -json build.json' build.v + +nextpnr-ecp5 --25k --package CSFBGA285 --json build.json --textcfg build.config --lpf $BOARD_DIR/pinout.lpf --timing-allow-fail --freq 38.8 + +ecppack --freq 38.8 --compress build.config build.bit + +cp build.bit build.dfu +dfu-suffix -v 1209 -p 5af0 -a build.dfu +dfu-util -D build.dfu +`define ORANGECRAB 1 +`default_nettype none +$$ORANGECRAB=1 +$$HARDWARE=1 +$$NUM_LEDS=3 + +module top( + input CLK, // 38.8 MHz + // bare + output [2:0] LED + ); + +// input/output wires + +wire [2:0] __main_out_leds; + +assign LED = __main_out_leds; + +// reset + +reg ready = 0; + +reg [15:0] RST_d; +reg [15:0] RST_q; + +always @* begin + RST_d = RST_q >> 1; +end + +always @(posedge CLK) begin + if (ready) begin + RST_q <= RST_d; + end else begin + ready <= 1; + RST_q <= 16'b1111111111111111; + end +end + +// main + +wire run_main; +assign run_main = 1'b1; + +M_main __main( + .clock (CLK), + .reset (RST_q[0]), + .in_run (run_main), + .out_leds (__main_out_leds) +); + +endmodule +{ + "name": "orangecrab", + "variants": [ + { + "name" : "r2_0", + "framework" : "orangecrab.v", + "pins" : [ + {"set" : "basic"} + ], + "builders": [ + { + "builder" : "edalize", + "description": "Build using Edalize", + "tool": "trellis", + "tool_options": [ + { + "nextpnr_options": ["--25k", "--freq 38.8", "--package CSFBGA285", "--timing-allow-fail"], + "pnr": "next" + } + ], + "bitstream" : "build.dfu", + "constraints": [{"name": "pinout.lpf", "file_type": "LPF"}], + "program": [ + {"cmd" : "cp", "args" : "build.bit build.dfu"}, + {"cmd" : "dfu-suffix", "args" : "-v 1209 -p 5af0 -a build.dfu"}, + {"cmd" : "dfu-util", "args" : "-D build.dfu"} + ] + }, + { + "builder" : "shell", + "command" : "orangecrab.sh", + "description": "Custom shell scripts using yosys and nextpnr" + } + ] + } + ], + "pins": { + "basic": [ + { + "name": "led", + "type": "uint3", + "io": "output" + } + ] + } +} +# base on https://github.com/FPGAwars/icestudio/blob/develop/app/resources/boards/orangecrab-r02-25f/pinout.lpf + +LOCATE COMP "CLK" SITE "A9"; # input +IOBUF PORT "CLK" IO_TYPE=LVCMOS33; + +LOCATE COMP "LED[0]" SITE "K4"; # output +LOCATE COMP "LED[1]" SITE "M3"; # output +LOCATE COMP "LED[2]" SITE "J3"; # output + +LOCATE COMP "RST" SITE "T15"; # inout +LOCATE COMP "A[0]" SITE "L4"; # inout +LOCATE COMP "A[1]" SITE "N3"; # inout +LOCATE COMP "A[2]" SITE "N4"; # inout +LOCATE COMP "A[3]" SITE "H4"; # inout +LOCATE COMP "A[4]" SITE "G4"; # inout +LOCATE COMP "A[5]" SITE "T17"; # inout +LOCATE COMP "SCK" SITE "R17"; # inout +LOCATE COMP "MOSI" SITE "N16"; # inout +LOCATE COMP "MISO" SITE "N15"; # inout +LOCATE COMP "G[0]" SITE "N17"; # inout +LOCATE COMP "G[1]" SITE "M18"; # inout +LOCATE COMP "SDA" SITE "C10"; # inout +LOCATE COMP "SCL" SITE "C9"; # inout +LOCATE COMP "G[5]" SITE "B10"; # inout +LOCATE COMP "G[6]" SITE "B9"; # inout +LOCATE COMP "G[9]" SITE "C8"; # inout +LOCATE COMP "G[10]" SITE "B8"; # inout +LOCATE COMP "G[11]" SITE "A8"; # inout +LOCATE COMP "G[12]" SITE "H2"; # inout +LOCATE COMP "G[13]" SITE "J2"; # inout + +# TODO: add PROGRAMN and PULLMODEs if any + +IOBUF PORT "LED[0]" IO_TYPE=LVCMOS33; +IOBUF PORT "LED[1]" IO_TYPE=LVCMOS33; +IOBUF PORT "LED[2]" IO_TYPE=LVCMOS33; + +IOBUF PORT "RST" IO_TYPE=LVCMOS33; +IOBUF PORT "A[0]" IO_TYPE=LVCMOS33; +IOBUF PORT "A[1]" IO_TYPE=LVCMOS33; +IOBUF PORT "A[2]" IO_TYPE=LVCMOS33; +IOBUF PORT "A[3]" IO_TYPE=LVCMOS33; +IOBUF PORT "A[4]" IO_TYPE=LVCMOS33; +IOBUF PORT "A[5]" IO_TYPE=LVCMOS33; +IOBUF PORT "SCK" IO_TYPE=LVCMOS33; +IOBUF PORT "MOSI" IO_TYPE=LVCMOS33; +IOBUF PORT "MISO" IO_TYPE=LVCMOS33; +IOBUF PORT "G[0]" IO_TYPE=LVCMOS33; +IOBUF PORT "G[1]" IO_TYPE=LVCMOS33; +IOBUF PORT "SDA" IO_TYPE=LVCMOS33; +IOBUF PORT "SCL" IO_TYPE=LVCMOS33; +IOBUF PORT "G[5]" IO_TYPE=LVCMOS33; +IOBUF PORT "G[6]" IO_TYPE=LVCMOS33; +IOBUF PORT "G[9]" IO_TYPE=LVCMOS33; +IOBUF PORT "G[10]" IO_TYPE=LVCMOS33; +IOBUF PORT "G[11]" IO_TYPE=LVCMOS33; +IOBUF PORT "G[12]" IO_TYPE=LVCMOS33; +IOBUF PORT "G[13]" IO_TYPE=LVCMOS33; +#============================================================ +# Additional settings +#============================================================ + +set_global_assignment -name ALLOW_ANY_ROM_SIZE_FOR_RECOGNITION ON +set_global_assignment -name ALLOW_ANY_RAM_SIZE_FOR_RECOGNITION ON + +#============================================================ +# Clocks +#============================================================ + +# set_location_assignment PIN_V11 -to clk +# set_location_assignment PIN_E11 -to clk +set_location_assignment PIN_Y13 -to clk +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to clk + +#============================================================ +# LEDs +#============================================================ + +set_location_assignment PIN_W15 -to leds[0] +set_location_assignment PIN_AA24 -to leds[1] +set_location_assignment PIN_V16 -to leds[2] +set_location_assignment PIN_V15 -to leds[3] +set_location_assignment PIN_AF26 -to leds[4] +set_location_assignment PIN_AE26 -to leds[5] +set_location_assignment PIN_Y16 -to leds[6] +set_location_assignment PIN_AA23 -to leds[7] + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds* + +#============================================================ +# Keypad +#============================================================ + +set_location_assignment PIN_AC24 -to kpadC[0] +set_location_assignment PIN_AD26 -to kpadC[1] +set_location_assignment PIN_AF28 -to kpadC[2] +set_location_assignment PIN_AF27 -to kpadC[3] +set_location_assignment PIN_Y15 -to kpadR[0] +set_location_assignment PIN_AA15 -to kpadR[1] +set_location_assignment PIN_AG28 -to kpadR[2] +set_location_assignment PIN_AE25 -to kpadR[3] + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to kpadC* +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to kpadR* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to kpadR* + +#============================================================ +# Switches and Buttons +#============================================================ + +set_location_assignment PIN_AH24 -to btns[0] +set_location_assignment PIN_AG25 -to btns[1] +set_location_assignment PIN_AG23 -to btns[2] +set_location_assignment PIN_AH17 -to btns[3] +set_location_assignment PIN_AH16 -to btns[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to btns* + +#============================================================ +# VGA (I/O board compatible) +#============================================================ + +set_location_assignment PIN_AE17 -to vga_r[0] +set_location_assignment PIN_AE20 -to vga_r[1] +set_location_assignment PIN_AF20 -to vga_r[2] +set_location_assignment PIN_AH18 -to vga_r[3] +set_location_assignment PIN_AH19 -to vga_r[4] +set_location_assignment PIN_AF21 -to vga_r[5] + +set_location_assignment PIN_AE19 -to vga_g[0] +set_location_assignment PIN_AG15 -to vga_g[1] +set_location_assignment PIN_AF18 -to vga_g[2] +set_location_assignment PIN_AG18 -to vga_g[3] +set_location_assignment PIN_AG19 -to vga_g[4] +set_location_assignment PIN_AG20 -to vga_g[5] + +set_location_assignment PIN_AG21 -to vga_b[0] +set_location_assignment PIN_AA20 -to vga_b[1] +set_location_assignment PIN_AE22 -to vga_b[2] +set_location_assignment PIN_AF22 -to vga_b[3] +set_location_assignment PIN_AH23 -to vga_b[4] +set_location_assignment PIN_AH21 -to vga_b[5] + +set_location_assignment PIN_AH22 -to vga_hs +set_location_assignment PIN_AG24 -to vga_vs + +set_location_assignment PIN_AH27 -to vga_en +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to vga_en + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to vga_* +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to vga_* + +#============================================================ +# SDRAM +#============================================================ + +set_location_assignment PIN_Y11 -to SDRAM_A[0] +set_location_assignment PIN_AA26 -to SDRAM_A[1] +set_location_assignment PIN_AA13 -to SDRAM_A[2] +set_location_assignment PIN_AA11 -to SDRAM_A[3] +set_location_assignment PIN_W11 -to SDRAM_A[4] +set_location_assignment PIN_Y19 -to SDRAM_A[5] +set_location_assignment PIN_AB23 -to SDRAM_A[6] +set_location_assignment PIN_AC23 -to SDRAM_A[7] +set_location_assignment PIN_AC22 -to SDRAM_A[8] +set_location_assignment PIN_C12 -to SDRAM_A[9] +set_location_assignment PIN_AB26 -to SDRAM_A[10] +set_location_assignment PIN_AD17 -to SDRAM_A[11] +set_location_assignment PIN_D12 -to SDRAM_A[12] +set_location_assignment PIN_Y17 -to SDRAM_BA[0] +set_location_assignment PIN_AB25 -to SDRAM_BA[1] +set_location_assignment PIN_E8 -to SDRAM_DQ[0] +set_location_assignment PIN_V12 -to SDRAM_DQ[1] +set_location_assignment PIN_D11 -to SDRAM_DQ[2] +set_location_assignment PIN_W12 -to SDRAM_DQ[3] +set_location_assignment PIN_AH13 -to SDRAM_DQ[4] +set_location_assignment PIN_D8 -to SDRAM_DQ[5] +set_location_assignment PIN_AH14 -to SDRAM_DQ[6] +set_location_assignment PIN_AF7 -to SDRAM_DQ[7] +set_location_assignment PIN_AE24 -to SDRAM_DQ[8] +set_location_assignment PIN_AD23 -to SDRAM_DQ[9] +set_location_assignment PIN_AE6 -to SDRAM_DQ[10] +set_location_assignment PIN_AE23 -to SDRAM_DQ[11] +set_location_assignment PIN_AG14 -to SDRAM_DQ[12] +set_location_assignment PIN_AD5 -to SDRAM_DQ[13] +set_location_assignment PIN_AF4 -to SDRAM_DQ[14] +set_location_assignment PIN_AH3 -to SDRAM_DQ[15] +set_location_assignment PIN_AG13 -to SDRAM_DQML +set_location_assignment PIN_AF13 -to SDRAM_DQMH +set_location_assignment PIN_AD20 -to SDRAM_CLK +set_location_assignment PIN_AG10 -to SDRAM_CKE +set_location_assignment PIN_AA19 -to SDRAM_nWE +set_location_assignment PIN_AA18 -to SDRAM_nCAS +set_location_assignment PIN_Y18 -to SDRAM_nCS +set_location_assignment PIN_W14 -to SDRAM_nRAS + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_* +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_* +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM_* +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQML +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQMH + +#============================================================ +# UART +#============================================================ + +set_location_assignment PIN_AG11 -to uart_rx +set_location_assignment PIN_AH9 -to uart_tx +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart_rx +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart_tx + +set_location_assignment PIN_AG8 -to uart2_rx +set_location_assignment PIN_AH8 -to uart2_tx +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart2_rx +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart2_tx +{ + "name": "de10nano", + "variants": [ + { + "name": "configurable", + "framework" : "de10nano.v", + "pins": [ + {"set" : "basic"}, + {"set" : "buttons","define" : "BUTTONS=1"}, + {"set" : "vga", "define" : "VGA=1"}, + {"set" : "sdram", "define" : "SDRAM=1"}, + {"set" : "uart", "define" : "UART=1"}, + {"set" : "uart2", "define" : "UART2=1"}, + {"set" : "keypad", "define" : "KEYPAD=1"} + ], + "builders": [ + { + "builder" : "edalize", + "description": "Build using Edalize", + "tool": "quartus", + "tool_options": [ + { + "family": "Cyclone V", + "device": "5CSEBA6U23I7", + "cable" : "DE-SoC", + "board_device_index" : 2 + } + ], + "toplevel" : "top", + "bitstream" : "build.sof", + "constraints": [ + {"name": "build.sdc", "file_type": "SDC"}, + {"name": "pins.tcl", "file_type": "tclSource"} + ], + "program": [ + {"cmd" : "quartus_pgm", "args" : "-m jtag -o \"p;build.sof@2\""} + ] + } + ] + } + ], + "pins": { + "basic": [ + { + "name": "leds", + "type": "uint8", + "io" : "output" + } + ], + "uart": [ + { + "name": "uart_tx", + "type": "uint1", + "io" : "output" + }, + { + "name": "uart_rx", + "type": "uint1", + "io" : "input" + } + ], + "uart2": [ + { + "name": "tx", + "type": "uint1", + "io" : "output" + }, + { + "name": "rx", + "type": "uint1", + "io" : "input" + } + ], + "keypad" : [ + { + "name": "kpadC", + "type": "uint4", + "io" : "output" + }, + { + "name": "kpadR", + "type": "uint4", + "io" : "input" + } + ], + "buttons" : [ + { + "name": "btns", + "type": "uint5", + "io" : "input" + } + ], + "sdram": [ + { + "name": "sdram_dq", + "type": "uint16", + "io": "inout" + }, + { + "name": "sdram_clk", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_cle", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_dqm", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_cs", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_we", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_cas", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_ras", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_ba", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_a", + "type": "uint1", + "io": "output" + } + ], + "vga": [ + { + "name": "vga_hs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_vs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_r", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_g", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_b", + "type": "uint6", + "io": "output" + } + ] + } +} +# inform quartus that the clk port brings a 50MHz clock into our design so +# that timing closure on our design can be analyzed + +create_clock -name clk -period "50MHz" [get_ports clk] +derive_pll_clocks -create_base_clocks +derive_clock_uncertainty + +# inform quartus that the LED output port has no critical timing requirements +# its a single output port driving an LED, there are no timing relationships +# that are critical for this + +set_false_path -from * -to [get_ports leds[0]] +set_false_path -from * -to [get_ports leds[1]] +set_false_path -from * -to [get_ports leds[2]] +set_false_path -from * -to [get_ports leds[3]] +set_false_path -from * -to [get_ports leds[4]] +set_false_path -from * -to [get_ports leds[5]] +set_false_path -from * -to [get_ports leds[6]] +set_false_path -from * -to [get_ports leds[7]] +`define DE10NANO 1 +$$DE10NANO = 1 +$$HARDWARE = 1 +$$NUM_LEDS = 8 +$$NUM_BTNS = 5 +$$if YOSYS then +$$config['bram_wenable_width'] = 'data' +$$config['dualport_bram_wenable0_width'] = 'data' +$$config['dualport_bram_wenable1_width'] = 'data' +$$else +$$config['dualport_bram_template'] = 'dualport_bram_altera.v.in' +$$end +$$color_depth = 6 +$$color_max = 63 + +`ifdef UART +`ifdef UART2 + `error_choose_either_uart_or_uart2 +`endif +`endif + +module top( + output [7:0] leds, +`ifdef BUTTONS + // buttons + input [4:0] btns, +`endif +`ifdef SDRAM + // sdram + output SDRAM_CLK, + output SDRAM_CKE, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nCS, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output [1:0] SDRAM_BA, + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, +`endif +`ifdef VGA + // vga + output vga_hs, + output vga_vs, + output [5:0] vga_r, + output [5:0] vga_g, + output [5:0] vga_b, +`endif +`ifdef UART + // uart + input uart_rx, + output uart_tx, +`endif +`ifdef UART2 + // uart, second choice + input uart2_rx, + output uart2_tx, +`endif +`ifdef KEYPAD + // keypad + output [3:0] kpadC, + input [3:0] kpadR, +`endif + // clock + input clk +); + +wire [7:0] __main_out_leds; + +`ifdef SDRAM +wire __main_out_sdram_clk; +wire __main_out_sdram_cle; +wire [1:0] __main_out_sdram_dqm; +wire __main_out_sdram_cs; +wire __main_out_sdram_we; +wire __main_out_sdram_cas; +wire __main_out_sdram_ras; +wire [1:0] __main_out_sdram_ba; +wire [12:0] __main_out_sdram_a; +`endif + +`ifdef VGA +wire __main_out_vga_hs; +wire __main_out_vga_vs; +wire [5:0] __main_out_vga_r; +wire [5:0] __main_out_vga_g; +wire [5:0] __main_out_vga_b; +`endif + +`ifdef UART +wire __main_out_uart_tx; +`endif +`ifdef UART2 +wire __main_out_uart_tx; +`endif + +`ifdef KEYPAD +wire [3:0] __main_out_kpadC; +`endif + +// reset + +reg [31:0] RST_d; +reg [31:0] RST_q; + +reg ready = 0; + +always @* begin + RST_d = RST_q >> 1; +end + +always @(posedge clk) begin + if (ready) begin + RST_q <= RST_d; + end else begin + ready <= 1; + RST_q <= 32'b111111111111111111111111111111; + end +end + +wire reset_main; +assign reset_main = RST_q[0]; +wire run_main; +assign run_main = 1'b1; + +M_main __main( + .reset(reset_main), + .in_run(run_main), + .out_leds(__main_out_leds), +`ifdef BUTTONS + .in_btns(btns), +`endif +`ifdef SDRAM + .inout_sdram_dq(SDRAM_DQ), + .out_sdram_clk(__main_out_sdram_clk), + .out_sdram_cle(__main_out_sdram_cle), + .out_sdram_dqm(__main_out_sdram_dqm), + .out_sdram_cs(__main_out_sdram_cs), + .out_sdram_we(__main_out_sdram_we), + .out_sdram_cas(__main_out_sdram_cas), + .out_sdram_ras(__main_out_sdram_ras), + .out_sdram_ba(__main_out_sdram_ba), + .out_sdram_a(__main_out_sdram_a), +`endif +`ifdef VGA + .out_video_hs(__main_out_vga_hs), + .out_video_vs(__main_out_vga_vs), + .out_video_r(__main_out_vga_r), + .out_video_g(__main_out_vga_g), + .out_video_b(__main_out_vga_b), +`endif +`ifdef UART + .out_uart_tx(__main_out_uart_tx), + .in_uart_rx(uart_rx), +`endif +`ifdef UART2 + .out_uart_tx(__main_out_uart_tx), + .in_uart_rx(uart2_rx), +`endif +`ifdef KEYPAD + .out_kpadC(__main_out_kpadC), + .in_kpadR(kpadR), +`endif + .clock(clk) +); + +assign leds = __main_out_leds; + +`ifdef SDRAM +assign SDRAM_CLK = __main_out_sdram_clk; +assign SDRAM_CKE = __main_out_sdram_cle; +assign SDRAM_DQML = __main_out_sdram_dqm[0]; +assign SDRAM_DQMH = __main_out_sdram_dqm[1]; +assign SDRAM_nCS = __main_out_sdram_cs; +assign SDRAM_nWE = __main_out_sdram_we; +assign SDRAM_nCAS = __main_out_sdram_cas; +assign SDRAM_nRAS = __main_out_sdram_ras; +assign SDRAM_BA = __main_out_sdram_ba; +assign SDRAM_A = __main_out_sdram_a; +`endif + +`ifdef VGA +assign vga_hs = __main_out_vga_hs; +assign vga_vs = __main_out_vga_vs; +assign vga_r = __main_out_vga_r; +assign vga_g = __main_out_vga_g; +assign vga_b = __main_out_vga_b; +`endif + +`ifdef UART +assign uart_tx = __main_out_uart_tx; +`endif +`ifdef UART2 +assign uart2_tx = __main_out_uart_tx; +`endif + +`ifdef KEYPAD +assign kpadC = __main_out_kpadC; +`endif + +endmodule +#!/bin/bash + +case "$(uname -s)" in +MINGW*|CYGWIN*) +SILICE_DIR=`cygpath $SILICE_DIR` +BUILD_DIR=`cygpath $BUILD_DIR` +FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR` +FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE` +BOARD_DIR=`cygpath $BOARD_DIR` +;; +*) +esac + +echo "build script: SILICE_DIR = $SILICE_DIR" +echo "build script: BUILD_DIR = $BUILD_DIR" +echo "build script: BOARD_DIR = $BOARD_DIR" +echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR" +echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE" + +export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR:"/c/Program Files (x86)/Graphviz2.38/bin/" +case "$(uname -s)" in +MINGW*) +export PYTHONHOME=/mingw64/bin +export PYTHONPATH=/mingw64/lib/python3.8/ +export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins +;; +*) +esac + +cd $BUILD_DIR + +rm build.v + +silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}" + +yosys -p 'synth_ice40 ; show -width -stretch -colors 4242' build.v + +dot -Tpdf:cairo show.dot -O +`define YOSYS 1 +`default_nettype none +$$HARDWARE = 1 +$$NUM_LEDS = 4 + +module top( + // LED outputs + output [3:0] leds, + input clk +); + + wire [7:0] __main_leds; + + reg reset = 1; + + always @(posedge clk) begin + if (reset) begin + reset <= 0; + end + end + + M_main __main( + .clock (clk), + .reset (reset), + .out_leds (__main_leds), + .in_run (~reset) + ); + + assign leds = __main_leds; + +endmodule +{ + "name": "techgraph", + "variants": [ + { + "name" : "techgraph", + "framework" : "techgraph.v", + "pins" : [ + {"set" : "basic"} + ], + "builders": [ + { + "builder" : "shell", + "command" : "techgraph.sh", + "description": "Custom shell scripts using yosys and nextpnr" + } + ] + } + ], + "pins": { + "basic": [ + { + "name": "leds", + "type": "uint8", + "io": "output" + } + ] + } +} +`define VERILATOR 1 +`define COLOR_DEPTH 1 + +/*verilator lint_off pinmissing */ +/*verilator lint_off undriven */ + +$$VERILATOR = 1 +$$NUM_LEDS = 0 +$$SIMULATION = 1 +$$color_depth = 1 +$$color_max = 1 + +`timescale 1ns / 1ps +`default_nettype none + +module top( + // NTSC + output reg [`COLOR_DEPTH*3-1:0] rgb, + output hsync, + output vsync, + input clk, + input reset + ); + +wire [`COLOR_DEPTH-1:0] __main_video_r; +wire [`COLOR_DEPTH-1:0] __main_video_g; +wire [`COLOR_DEPTH-1:0] __main_video_b; +wire __main_video_hs; +wire __main_video_vs; + +// main + +wire run_main; +assign run_main = 1'b1; +wire done_main; + +M_main __main( + .clock(clk), + .reset(reset), +`ifdef NTSC + .out_video_r(__main_video_r), + .out_video_g(__main_video_g), + .out_video_b(__main_video_b), + .out_video_hs(__main_video_hs), + .out_video_vs(__main_video_vs), +`endif + .in_run(run_main), + .out_done(done_main) +); + +assign rgb = {__main_video_b[0], __main_video_g[0], __main_video_r[0]}; +assign hsync = __main_video_hs; +assign vsync = __main_video_vs; + +endmodule +#!/bin/bash + +case "$(uname -s)" in +MINGW*|CYGWIN*) +SILICE_DIR=`cygpath $SILICE_DIR` +BUILD_DIR=`cygpath $BUILD_DIR` +FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR` +FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE` +BOARD_DIR=`cygpath $BOARD_DIR` +;; +*) +esac + +echo "build script: SILICE_DIR = $SILICE_DIR" +echo "build script: BUILD_DIR = $BUILD_DIR" +echo "build script: BOARD_DIR = $BOARD_DIR" +echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR" +echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE" + +if hash make 2>/dev/null; then + export MAKE=make +else + export MAKE=mingw32-make +fi + +export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR + +if [[ -z "${VERILATOR_ROOT}" ]]; then +case "$(uname -s)" in +Linux) +unset VERILATOR_ROOT +;; +*) +export VERILATOR_ROOT=$SILICE_DIR/../tools/fpga-binutils/mingw64/ +;; +esac +echo "VERILATOR_ROOT is set to ${VERILATOR_ROOT}" +else +echo "VERILATOR_ROOT already defined, using its value" +fi + +u=$(echo "$1" | sed s:/:__:g | tr -d ".") + +echo "using directory $u" + +cd $BUILD_DIR + +silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}" + +if [[ -z "${VGA}" ]] && [[ -z "${SDRAM}" ]]; then +VERILATOR_LIB="verilator_bare" +else +VERILATOR_LIB="verilator_vga" +fi + +#echo "using verilator framework $VERILATOR_LIB" + +#verilator -Wno-PINMISSING -Wno-WIDTH -O3 -cc build.v --top-module top +#cd obj_dir +#$MAKE -f Vtop.mk +#$MAKE -f Vtop.mk $SILICE_DIR/../frameworks/verilator/$VERILATOR_LIB.o verilated.o +#g++ -O3 $SILICE_DIR/../frameworks/verilator/$VERILATOR_LIB.o verilated.o Vtop__ALL.a $SILICE_DIR/../frameworks/verilator/libverilator_silice.a -o ../run_simul +#cd .. + +#./run_simul +{ + "name": "8bitworkshop", + "variants": [ + { + "name" : "configurable", + "framework" : "8bitworkshop.v", + "pins" : [ + {"set" : "ntsc", "define" : "NTSC=1"} + ], + "builders": [ + { + "builder" : "shell", + "command" : "8bitworkshop.sh", + "description": "Simulates with 8bitworkshop" + } + ] + } + ], + "pins": { + "ntsc": [ + { + "name": "hsync", + "type": "uint1", + "io": "output" + }, + { + "name": "vsync", + "type": "uint1", + "io": "output" + }, + { + "name": "rgb", + "type": "uint3", + "io": "output" + } + ], + "paddles": [ + { + "name": "hpaddle", + "type": "uint1", + "io": "input" + }, + { + "name": "vpaddle", + "type": "uint1", + "io": "input" + } + ], + "switches": [ + { + "name": "switches_p1", + "type": "uint8", + "io": "input" + }, + { + "name": "switches_p2", + "type": "uint8", + "io": "input" + } + ], + "keyboard": [ + { + "name": "keycode", + "type": "uint8", + "io": "input" + }, + { + "name": "keystrobe", + "type": "uint1", + "io": "output" + } + ] + } +} +{ + "name": "fomu", + "variants": [ + { + "name" : "hacker", + "framework" : "fomu.v", + "pins" : [ + {"set" : "basic"}, + {"set" : "usb", "define" : "USB=1"}, + {"set" : "spi", "define" : "SPI=1"}, + {"set" : "pads", "define" : "PADS=1"} + ], + "builders": [ + { + "builder" : "shell", + "command" : "fomu.sh", + "description": "Custom shell scripts using yosys and nextpnr" + } + ] + } + ], + "pins": { + "basic": [ + { + "name": "leds", + "type": "uint3", + "io": "output" + } + ], + "usb": [ + { + "name": "usb_dp", + "type": "uint1", + "io": "output" + }, + { + "name": "usb_dn", + "type": "uint1", + "io": "output" + }, + { + "name": "usb_dp_pu", + "type": "uint1", + "io": "output" + } + ], + "spi": [ + { + "name": "spi_mosi", + "type": "uint1", + "io": "output" + }, + { + "name": "spi_miso", + "type": "uint1", + "io": "input" + }, + { + "name": "spi_clk", + "type": "uint1", + "io": "output" + }, + { + "name": "spi_cs", + "type": "uint1", + "io": "output" + } + ], + "pads": [ + { + "name": "user_pads", + "type": "uint4", + "io": "input" + } + ] + } +} +# Configuration for the Fomu hacker board. +set_io rgb0 A5 # Blue LED +set_io rgb1 B5 # Green LED +set_io rgb2 C5 # Red LED +set_io clki F5 # Clock input from 48MHz Oscillator +set_io spi_mosi F1 # SPI Master Out, Slave In Pin +set_io spi_miso E1 # SPI Master In, Slave Out Pin +set_io spi_clk D1 # SPI Master Clock Output Pin +set_io spi_cs C1 # SPI Chip Select +set_io user_1 F4 # User touch pad 1 +set_io user_2 E5 # User touch pad 2 +set_io user_3 E4 # User touch pad 3 +set_io user_4 F2 # User touch pad 4 +set_io usb_dn A2 # USB D- pad +set_io usb_dp A4 # USB D+ pad +set_io usb_dp_pu D5 # USB D+ pull up (indicates device connected) +// credits: rob-ng15 - see also https://github.com/rob-ng15/Silice-Playground/ +`define FOMU 1 +`default_nettype none +$$FOMU = 1 +$$HARDWARE = 1 +$$NUM_LEDS = 3 + +// Correctly map pins for the iCE40UP5K SB_RGBA_DRV hard macro. +// The variables EVT, PVT and HACKER are set from the yosys commandline e.g. yosys -D HACKER=1 +`ifdef EVT +`define BLUEPWM RGB0PWM +`define REDPWM RGB1PWM +`define GREENPWM RGB2PWM +`elsif HACKER +`define BLUEPWM RGB0PWM +`define GREENPWM RGB1PWM +`define REDPWM RGB2PWM +`elsif PVT +`define GREENPWM RGB0PWM +`define REDPWM RGB1PWM +`define BLUEPWM RGB2PWM +`else +`error_board_not_supported +`endif + +module top( + // LED outputs + output rgb0, + output rgb1, + output rgb2, + // USB Pins + output usb_dp, + output usb_dn, + output usb_dp_pu, +`ifdef SPI + // SPI + output spi_mosi, + input spi_miso, + output spi_clk, + output spi_cs, +`endif +`ifdef PADS + // USER pads + input [3:0] user_pads, +`endif + // 48MHz Clock Input + input clki +); + +`ifdef USB + wire __main_usb_dp; + wire __main_usb_dn; + wire __main_usb_dp_pu; + assign usb_dp = __main_usb_dp; + assign usb_dn = __main_usb_dn; + assign usb_dp_pu = __main_usb_dp_pu; +`else + // Assign USB pins to "0" so as to disconnect Fomu from + // the host system. Otherwise it would try to talk to + // us over USB, which wouldn't work since we have no stack. + assign usb_dp = 1'b0; + assign usb_dn = 1'b0; + assign usb_dp_pu = 1'b0; +`endif + +`ifdef SPI + wire __main_spi_mosi; + wire __main_spi_clk; + wire __main_spi_cs; + assign spi_mosi = __main_spi_mosi; + assign spi_clk = __main_spi_clk; + assign spi_cs = __main_spi_cs; +`endif + + // Connect to system clock (with buffering) + wire clk; + SB_GB clk_gb ( + .USER_SIGNAL_TO_GLOBAL_BUFFER(clki), + .GLOBAL_BUFFER_OUTPUT(clk) + ); + + wire [2:0] __main_leds; + + reg [31:0] RST_d; + reg [31:0] RST_q; + + reg ready = 0; + + always @* begin + RST_d = RST_q >> 1; + end + + always @(posedge clk) begin + if (ready) begin + RST_q <= RST_d; + end else begin + ready <= 1; + RST_q <= 32'b111111111111111111111111111111; + end + end + + wire reset_main; + assign reset_main = RST_q[0]; + wire run_main; + assign run_main = 1'b1; + + M_main __main( + .clock (clk), + .reset (RST_q[0]), + .out_leds (__main_leds), +`ifdef USB + .out_usb_dp (__main_usb_dp), + .out_usb_dn (__main_usb_dn), + .out_usb_dp_pu(__main_usb_dp_pu), +`endif +`ifdef SPI + .out_spi_mosi (__main_spi_mosi), + .in_spi_miso (spi_miso), + .out_spi_clk (__main_spi_clk), + .out_spi_cs (__main_spi_cs), +`endif +`ifdef PADS + .in_user_pads(user_pads), +`endif + .in_run (run_main) + ); + + SB_RGBA_DRV #( + .CURRENT_MODE("0b1"), // half current + .RGB0_CURRENT("0b000011"), // 4 mA + .RGB1_CURRENT("0b000011"), // 4 mA + .RGB2_CURRENT("0b000011") // 4 mA + ) RGBA_DRIVER ( + .CURREN(1'b1), + .RGBLEDEN(1'b1), + .`BLUEPWM (__main_leds[0]), // Blue + .`REDPWM (__main_leds[1]), // Red + .`GREENPWM(__main_leds[2]), // Green + .RGB0(rgb0), + .RGB1(rgb1), + .RGB2(rgb2) + ); + +endmodule +#!/bin/bash + +# credits: rob-ng15 -- see also https://github.com/rob-ng15/Silice-Playground + +case "$(uname -s)" in +MINGW*|CYGWIN*) +SILICE_DIR=`cygpath $SILICE_DIR` +BUILD_DIR=`cygpath $BUILD_DIR` +FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR` +FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE` +BOARD_DIR=`cygpath $BOARD_DIR` +;; +*) +esac + +echo "build script: SILICE_DIR = $SILICE_DIR" +echo "build script: BUILD_DIR = $BUILD_DIR" +echo "build script: BOARD_DIR = $BOARD_DIR" +echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR" +echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE" + +export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR +case "$(uname -s)" in +MINGW*) +export PYTHONHOME=/mingw64/bin +export PYTHONPATH=/mingw64/lib/python3.8/ +export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins +;; +*) +esac + +cd $BUILD_DIR + +rm build* + +silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}" + +yosys -D HACKER=1 -p 'synth_ice40 -top top -json build.json' build.v + +nextpnr-ice40 --up5k --package uwg30 --opt-timing --pcf $BOARD_DIR/fomu-hacker.pcf --json build.json --asc build.asc + +icepack build.asc build.bit +icetime -d up5k -mtr build.rpt build.asc + +cp build.bit build.dfu +dfu-suffix -v 1209 -p 70b1 -a build.dfu +dfu-util -D build.dfu +`define ULX3S 1 +`default_nettype none +$$ULX3S = 1 +$$HARDWARE = 1 +$$NUM_LEDS = 8 +$$NUM_BTNS = 7 +$$color_depth = 6 +$$color_max = 63 +$$config['dualport_bram_supported'] = 'no' + +module top( + // basic + output [7:0] leds, + // buttons + input [6:0] btns, +`ifdef SDRAM + // sdram + output sdram_clk, + output sdram_cke, + output [1:0] sdram_dqm, + output sdram_csn, + output sdram_wen, + output sdram_casn, + output sdram_rasn, + output [1:0] sdram_ba, + output [12:0] sdram_a, + inout [15:0] sdram_d, +`endif +`ifdef AUDIO + output [3:0] audio_l, + output [3:0] audio_r, +`endif +`ifdef OLED + // oled + output oled_clk, + output oled_mosi, + output oled_dc, + output oled_resn, + output oled_csn, +`endif +`ifdef SDCARD + // sdcard + output sd_clk, + output sd_csn, + output sd_mosi, + input sd_miso, +`endif +`ifdef GPIO + // gpio + output [27:0] gp, + input [27:0] gn, +`endif +`ifdef VGA + // vga + output [27:0] gp, + input [27:0] gn, +`endif +`ifdef HDMI + // hdmi + output [3:0] gpdi_dp, // {clock,R,G,B} + output [3:0] gpdi_dn, +`endif +`ifdef UART + // uart + output ftdi_rxd, + input ftdi_txd, +`endif +`ifdef UART2 + // uart2 +`endif + input clk_25mhz + ); + +wire [7:0] __main_out_leds; + +`ifdef OLED +wire __main_oled_clk; +wire __main_oled_mosi; +wire __main_oled_dc; +wire __main_oled_resn; +wire __main_oled_csn; +`endif + +`ifdef SDRAM +wire __main_out_sdram_clk; +wire __main_out_sdram_cle; +wire [1:0] __main_out_sdram_dqm; +wire __main_out_sdram_cs; +wire __main_out_sdram_we; +wire __main_out_sdram_cas; +wire __main_out_sdram_ras; +wire [1:0] __main_out_sdram_ba; +wire [12:0] __main_out_sdram_a; +`endif + +`ifdef UART2 +`ifndef GPIO +`error_UART2_needs_GPIO +`endif +`endif + +`ifdef UART +wire __main_out_uart_tx; +`endif + +`ifdef VGA +wire __main_out_vga_hs; +wire __main_out_vga_vs; +wire [5:0] __main_out_vga_r; +wire [5:0] __main_out_vga_g; +wire [5:0] __main_out_vga_b; +`endif + +`ifdef SDCARD +wire __main_sd_clk; +wire __main_sd_csn; +wire __main_sd_mosi; +`endif + +`ifdef HDMI +wire [3:0] __main_out_gpdi_dp; +wire [3:0] __main_out_gpdi_dn; +`endif + +`ifdef AUDIO +wire [3:0] __main_out_audio_l; +wire [3:0] __main_out_audio_r; +`endif + +wire ready = btns[0]; + +reg [31:0] RST_d; +reg [31:0] RST_q; + +always @* begin + RST_d = RST_q >> 1; +end + +always @(posedge clk_25mhz) begin + if (ready) begin + RST_q <= RST_d; + end else begin + RST_q <= 32'b111111111111111111111111111111; + end +end + +wire run_main; +assign run_main = 1'b1; + +M_main __main( + .reset (RST_q[0]), + .in_run (run_main), + .out_leds (__main_out_leds), +`ifdef BUTTONS + .in_btns (btns), +`endif +`ifdef SDRAM + .inout_sdram_dq(sdram_d), + .out_sdram_clk (__main_out_sdram_clk), + .out_sdram_cle (__main_out_sdram_cle), + .out_sdram_dqm (__main_out_sdram_dqm), + .out_sdram_cs (__main_out_sdram_cs), + .out_sdram_we (__main_out_sdram_we), + .out_sdram_cas (__main_out_sdram_cas), + .out_sdram_ras (__main_out_sdram_ras), + .out_sdram_ba (__main_out_sdram_ba), + .out_sdram_a (__main_out_sdram_a), +`endif +`ifdef SDCARD + .out_sd_csn (__main_sd_csn), + .out_sd_clk (__main_sd_clk), + .out_sd_mosi (__main_sd_mosi), + .in_sd_miso (sd_miso), +`endif +`ifdef AUDIO + .out_audio_l (__main_out_audio_l), + .out_audio_r (__main_out_audio_r), +`endif +`ifdef OLED + .out_oled_clk (__main_oled_clk), + .out_oled_mosi(__main_oled_mosi), + .out_oled_dc (__main_oled_dc), + .out_oled_resn(__main_oled_resn), + .out_oled_csn (__main_oled_csn), +`endif +`ifdef GPIO +`ifdef UART2 + .out_gp (gp[27:1]), + .in_gn (gn[27:1]), + .out_uart2_tx (gp[0]), + .in_uart2_rx (gn[0]), +`else + .out_gp (gp), + .in_gn (gn), +`endif +`endif +`ifdef UART + .out_uart_tx (__main_out_uart_tx), + .in_uart_rx (ftdi_txd), +`endif +`ifdef VGA + .out_video_hs (__main_out_vga_hs), + .out_video_vs (__main_out_vga_vs), + .out_video_r (__main_out_vga_r), + .out_video_g (__main_out_vga_g), + .out_video_b (__main_out_vga_b), +`endif +`ifdef HDMI + .out_gpdi_dp (__main_out_gpdi_dp), + .out_gpdi_dn (__main_out_gpdi_dn), +`endif + .clock (clk_25mhz) +); + +assign leds = __main_out_leds; + +`ifdef SDRAM +assign sdram_clk = __main_out_sdram_clk; +assign sdram_cke = __main_out_sdram_cle; +assign sdram_dqm = __main_out_sdram_dqm; +assign sdram_csn = __main_out_sdram_cs; +assign sdram_wen = __main_out_sdram_we; +assign sdram_casn = __main_out_sdram_cas; +assign sdram_rasn = __main_out_sdram_ras; +assign sdram_ba = __main_out_sdram_ba; +assign sdram_a = __main_out_sdram_a; +`endif + +`ifdef AUDIO +assign audio_l = __main_out_audio_l; +assign audio_r = __main_out_audio_r; +`endif + +`ifdef VGA +assign gp[0] = __main_out_vga_vs; +assign gp[1] = __main_out_vga_hs; +assign gp[2] = __main_out_vga_r[5]; +assign gp[3] = __main_out_vga_r[4]; +assign gp[4] = __main_out_vga_r[3]; +assign gp[5] = __main_out_vga_r[2]; +assign gp[6] = __main_out_vga_r[1]; +assign gp[7] = __main_out_vga_r[0]; +assign gp[8] = __main_out_vga_g[5]; +assign gp[9] = __main_out_vga_g[4]; +assign gp[10] = __main_out_vga_g[3]; +assign gp[11] = __main_out_vga_g[2]; +assign gp[12] = __main_out_vga_g[1]; +assign gp[13] = __main_out_vga_g[0]; +assign gp[14] = __main_out_vga_b[0]; +assign gp[15] = __main_out_vga_b[1]; +assign gp[16] = __main_out_vga_b[2]; +assign gp[17] = __main_out_vga_b[3]; +assign gp[18] = __main_out_vga_b[4]; +assign gp[19] = __main_out_vga_b[5]; +`endif + +`ifdef SDCARD +assign sd_clk = __main_sd_clk; +assign sd_csn = __main_sd_csn; +assign sd_mosi = __main_sd_mosi; +`endif + +`ifdef OLED +assign oled_clk = __main_oled_clk; +assign oled_mosi = __main_oled_mosi; +assign oled_dc = __main_oled_dc; +assign oled_resn = __main_oled_resn; +assign oled_csn = __main_oled_csn; +`endif + +`ifdef UART +assign ftdi_rxd = __main_out_uart_tx; +`endif + +`ifdef HDMI +assign gpdi_dp = __main_out_gpdi_dp; +assign gpdi_dn = __main_out_gpdi_dn; +`endif + +endmodule +# https://github.com/emard/ulx3s/blob/master/doc/constraints/ulx3s_v20.lpf + +BLOCK RESETPATHS; +BLOCK ASYNCPATHS; +## ULX3S v2.x.x and v3.0.x + +# The clock "usb" and "gpdi" sheet +LOCATE COMP "clk_25mhz" SITE "G2"; +IOBUF PORT "clk_25mhz" PULLMODE=NONE IO_TYPE=LVCMOS33; +FREQUENCY PORT "clk_25mhz" 25 MHZ; + +# JTAG and SPI FLASH voltage 3.3V and options to boot from SPI flash +# write to FLASH possible any time from JTAG: +#SYSCONFIG CONFIG_IOVOLTAGE=3.3 COMPRESS_CONFIG=ON MCCLK_FREQ=62 MASTER_SPI_PORT=ENABLE SLAVE_SPI_PORT=DISABLE SLAVE_PARALLEL_PORT=DISABLE; +# write to FLASH possible from user bitstream: +SYSCONFIG CONFIG_IOVOLTAGE=3.3 COMPRESS_CONFIG=ON MCCLK_FREQ=62 MASTER_SPI_PORT=DISABLE SLAVE_SPI_PORT=DISABLE SLAVE_PARALLEL_PORT=DISABLE; + +## USBSERIAL FTDI-FPGA serial port "usb" sheet +LOCATE COMP "ftdi_rxd" SITE "L4"; # FPGA transmits to ftdi +LOCATE COMP "ftdi_txd" SITE "M1"; # FPGA receives from ftdi +LOCATE COMP "ftdi_nrts" SITE "M3"; # FPGA receives +LOCATE COMP "ftdi_ndtr" SITE "N1"; # FPGA receives +LOCATE COMP "ftdi_txden" SITE "L3"; # FPGA receives +IOBUF PORT "ftdi_rxd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "ftdi_txd" PULLMODE=UP IO_TYPE=LVCMOS33; +IOBUF PORT "ftdi_nrts" PULLMODE=UP IO_TYPE=LVCMOS33; +IOBUF PORT "ftdi_ndtr" PULLMODE=UP IO_TYPE=LVCMOS33; +IOBUF PORT "ftdi_txden" PULLMODE=UP IO_TYPE=LVCMOS33; + +## LED indicators "blinkey" and "gpio" sheet +LOCATE COMP "leds[7]" SITE "H3"; +LOCATE COMP "leds[6]" SITE "E1"; +LOCATE COMP "leds[5]" SITE "E2"; +LOCATE COMP "leds[4]" SITE "D1"; +LOCATE COMP "leds[3]" SITE "D2"; +LOCATE COMP "leds[2]" SITE "C1"; +LOCATE COMP "leds[1]" SITE "C2"; +LOCATE COMP "leds[0]" SITE "B2"; +IOBUF PORT "leds[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "leds[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "leds[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "leds[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "leds[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "leds[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "leds[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "leds[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; + +## Pushbuttons "blinkey", "flash", "power", "gpdi" sheet +LOCATE COMP "btns[0]" SITE "D6"; # BTN_PWRn (inverted logic) +LOCATE COMP "btns[1]" SITE "R1"; # FIRE1 +LOCATE COMP "btns[2]" SITE "T1"; # FIRE2 +LOCATE COMP "btns[3]" SITE "R18"; # UP +LOCATE COMP "btns[4]" SITE "V1"; # DOWN +LOCATE COMP "btns[5]" SITE "U1"; # LEFT +LOCATE COMP "btns[6]" SITE "H16"; # RIGHT +IOBUF PORT "btns[0]" PULLMODE=UP IO_TYPE=LVCMOS33; +IOBUF PORT "btns[1]" PULLMODE=DOWN IO_TYPE=LVCMOS33; +IOBUF PORT "btns[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33; +IOBUF PORT "btns[3]" PULLMODE=DOWN IO_TYPE=LVCMOS33; +IOBUF PORT "btns[4]" PULLMODE=DOWN IO_TYPE=LVCMOS33; +IOBUF PORT "btns[5]" PULLMODE=DOWN IO_TYPE=LVCMOS33; +IOBUF PORT "btns[6]" PULLMODE=DOWN IO_TYPE=LVCMOS33; + +## DIP switch "blinkey", "gpio" sheet +LOCATE COMP "sw[0]" SITE "E8"; # SW1 +LOCATE COMP "sw[1]" SITE "D8"; # SW2 +LOCATE COMP "sw[2]" SITE "D7"; # SW3 +LOCATE COMP "sw[3]" SITE "E7"; # SW4 +IOBUF PORT "sw[0]" PULLMODE=DOWN IO_TYPE=LVCMOS33; +IOBUF PORT "sw[1]" PULLMODE=DOWN IO_TYPE=LVCMOS33; +IOBUF PORT "sw[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33; +IOBUF PORT "sw[3]" PULLMODE=DOWN IO_TYPE=LVCMOS33; + +## SPI OLED DISPLAY SSD1331 (Color) or SSD1306 (B/W) "blinkey", "usb" sheet +LOCATE COMP "oled_clk" SITE "P4"; +LOCATE COMP "oled_mosi" SITE "P3"; +LOCATE COMP "oled_dc" SITE "P1"; +LOCATE COMP "oled_resn" SITE "P2"; +LOCATE COMP "oled_csn" SITE "N2"; +IOBUF PORT "oled_clk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "oled_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "oled_dc" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "oled_resn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "oled_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; + +## SPI Flash chip "flash" sheet +LOCATE COMP "flash_csn" SITE "R2"; +#LOCATE COMP "flash_clk" SITE "U3"; +LOCATE COMP "flash_mosi" SITE "W2"; +LOCATE COMP "flash_miso" SITE "V2"; +LOCATE COMP "flash_holdn" SITE "W1"; +LOCATE COMP "flash_wpn" SITE "Y2"; +#LOCATE COMP "flash_csspin" SITE "AJ3"; +#LOCATE COMP "flash_initn" SITE "AG4"; +#LOCATE COMP "flash_done" SITE "AJ4"; +#LOCATE COMP "flash_programn" SITE "AH4"; +#LOCATE COMP "flash_cfg_select[0]" SITE "AM4"; +#LOCATE COMP "flash_cfg_select[1]" SITE "AL4"; +#LOCATE COMP "flash_cfg_select[2]" SITE "AK4"; +IOBUF PORT "flash_csn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +#IOBUF PORT "flash_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "flash_mosi" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "flash_miso" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "flash_holdn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "flash_wpn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +#IOBUF PORT "flash_csspin" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +#IOBUF PORT "flash_initn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +#IOBUF PORT "flash_done" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +#IOBUF PORT "flash_programn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +#IOBUF PORT "flash_cfg_select[0]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; +#IOBUF PORT "flash_cfg_select[1]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; +#IOBUF PORT "flash_cfg_select[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; + +## SD card "sdcard", "usb" sheet +LOCATE COMP "sd_clk" SITE "H2"; # sd_clk WiFi_GPIO14 +LOCATE COMP "sd_mosi" SITE "J1"; # sd_cmd_di (MOSI) WiFi GPIO15 +LOCATE COMP "sd_miso" SITE "J3"; # sd_dat0_do (MISO) WiFi GPIO2 +LOCATE COMP "sd_csn" SITE "K2"; # sd_dat3_csn WiFi_GPIO13 +IOBUF PORT "sd_clk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sd_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sd_miso" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sd_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; + +## ADC SPI (MAX11123) "analog", "ram" sheet +LOCATE COMP "adc_csn" SITE "R17"; +LOCATE COMP "adc_mosi" SITE "R16"; +LOCATE COMP "adc_miso" SITE "U16"; +LOCATE COMP "adc_sclk" SITE "P17"; +IOBUF PORT "adc_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "adc_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "adc_miso" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "adc_sclk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; + +## Audio 4-bit DAC "analog", "gpio" sheet +# Output impedance 75 ohm. +# Strong enough to drive 16 ohm earphones. +LOCATE COMP "audio_l[3]" SITE "B3"; # JACK TIP (left audio) +LOCATE COMP "audio_l[2]" SITE "C3"; +LOCATE COMP "audio_l[1]" SITE "D3"; +LOCATE COMP "audio_l[0]" SITE "E4"; +LOCATE COMP "audio_r[3]" SITE "C5"; # JACK RING1 (right audio) +LOCATE COMP "audio_r[2]" SITE "D5"; +LOCATE COMP "audio_r[1]" SITE "B5"; +LOCATE COMP "audio_r[0]" SITE "A3"; +LOCATE COMP "audio_v[3]" SITE "E5"; # JACK RING2 (video or digital audio) +LOCATE COMP "audio_v[2]" SITE "F5"; +LOCATE COMP "audio_v[1]" SITE "F2"; +LOCATE COMP "audio_v[0]" SITE "H5"; +IOBUF PORT "audio_l[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "audio_l[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "audio_l[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "audio_l[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "audio_r[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "audio_r[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "audio_r[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "audio_r[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "audio_v[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "audio_v[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "audio_v[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "audio_v[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; + +## WiFi ESP-32 "wifi", "usb", "flash" sheet +# other pins are shared with GP/GN, SD card and JTAG +LOCATE COMP "wifi_en" SITE "F1"; # enable/reset WiFi +LOCATE COMP "wifi_rxd" SITE "K3"; # FPGA transmits to WiFi +LOCATE COMP "wifi_txd" SITE "K4"; # FPGA receives from WiFi +LOCATE COMP "wifi_gpio0" SITE "L2"; +LOCATE COMP "wifi_gpio5" SITE "N4"; # WIFI LED +LOCATE COMP "wifi_gpio16" SITE "L1"; # Serial1 RX +LOCATE COMP "wifi_gpio17" SITE "N3"; # Serial1 TX +# LOCATE COMP "prog_done" SITE "Y3"; # not GPIO, always active +IOBUF PORT "wifi_en" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "wifi_rxd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "wifi_txd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "wifi_gpio0" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "wifi_gpio5" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "wifi_gpio16" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "wifi_gpio17" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +# IOBUF PORT "prog_done" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; + +## PCB antenna 433 MHz (may be also used for FM) "usb" sheet +LOCATE COMP "ant_433mhz" SITE "G1"; +IOBUF PORT "ant_433mhz" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; + +## Second USB port "US2" going directly into FPGA "usb", "ram" sheet +LOCATE COMP "usb_fpga_dp" SITE "E16"; # single ended or differential input only +LOCATE COMP "usb_fpga_dn" SITE "F16"; +IOBUF PORT "usb_fpga_dp" PULLMODE=NONE IO_TYPE=LVCMOS33D DRIVE=16; +IOBUF PORT "usb_fpga_dn" PULLMODE=NONE IO_TYPE=LVCMOS33D DRIVE=16; +LOCATE COMP "usb_fpga_bd_dp" SITE "D15"; # single-ended bidirectional +LOCATE COMP "usb_fpga_bd_dn" SITE "E15"; +IOBUF PORT "usb_fpga_bd_dp" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "usb_fpga_bd_dn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +LOCATE COMP "usb_fpga_pu_dp" SITE "B12"; # pull up/down control +LOCATE COMP "usb_fpga_pu_dn" SITE "C12"; +IOBUF PORT "usb_fpga_pu_dp" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; +IOBUF PORT "usb_fpga_pu_dn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16; + +## JTAG ESP-32 "usb" sheet +# connected to FT231X and ESP-32 +# commented out because those are dedicated pins, not directly useable as GPIO +# but could be used by some vendor-specific JTAG bridging (boundary scan) module +#LOCATE COMP "jtag_tdi" SITE "R5"; # FTDI_nRI FPGA receives +#LOCATE COMP "jtag_tdo" SITE "V4"; # FTDI_nCTS FPGA transmits +#LOCATE COMP "jtag_tck" SITE "T5"; # FTDI_nDSR FPGA receives +#LOCATE COMP "jtag_tms" SITE "U5"; # FTDI_nDCD FPGA receives +#IOBUF PORT "jtag_tdi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +#IOBUF PORT "jtag_tdo" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +#IOBUF PORT "jtag_tck" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +#IOBUF PORT "jtag_tms" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; + +## SDRAM "ram" sheet +LOCATE COMP "sdram_clk" SITE "F19"; +LOCATE COMP "sdram_cke" SITE "F20"; +LOCATE COMP "sdram_csn" SITE "P20"; +LOCATE COMP "sdram_wen" SITE "T20"; +LOCATE COMP "sdram_rasn" SITE "R20"; +LOCATE COMP "sdram_casn" SITE "T19"; +LOCATE COMP "sdram_a[0]" SITE "M20"; +LOCATE COMP "sdram_a[1]" SITE "M19"; +LOCATE COMP "sdram_a[2]" SITE "L20"; +LOCATE COMP "sdram_a[3]" SITE "L19"; +LOCATE COMP "sdram_a[4]" SITE "K20"; +LOCATE COMP "sdram_a[5]" SITE "K19"; +LOCATE COMP "sdram_a[6]" SITE "K18"; +LOCATE COMP "sdram_a[7]" SITE "J20"; +LOCATE COMP "sdram_a[8]" SITE "J19"; +LOCATE COMP "sdram_a[9]" SITE "H20"; +LOCATE COMP "sdram_a[10]" SITE "N19"; +LOCATE COMP "sdram_a[11]" SITE "G20"; +LOCATE COMP "sdram_a[12]" SITE "G19"; +LOCATE COMP "sdram_ba[0]" SITE "P19"; +LOCATE COMP "sdram_ba[1]" SITE "N20"; +LOCATE COMP "sdram_dqm[0]" SITE "U19"; +LOCATE COMP "sdram_dqm[1]" SITE "E20"; +LOCATE COMP "sdram_d[0]" SITE "J16"; +LOCATE COMP "sdram_d[1]" SITE "L18"; +LOCATE COMP "sdram_d[2]" SITE "M18"; +LOCATE COMP "sdram_d[3]" SITE "N18"; +LOCATE COMP "sdram_d[4]" SITE "P18"; +LOCATE COMP "sdram_d[5]" SITE "T18"; +LOCATE COMP "sdram_d[6]" SITE "T17"; +LOCATE COMP "sdram_d[7]" SITE "U20"; +LOCATE COMP "sdram_d[8]" SITE "E19"; +LOCATE COMP "sdram_d[9]" SITE "D20"; +LOCATE COMP "sdram_d[10]" SITE "D19"; +LOCATE COMP "sdram_d[11]" SITE "C20"; +LOCATE COMP "sdram_d[12]" SITE "E18"; +LOCATE COMP "sdram_d[13]" SITE "F18"; +LOCATE COMP "sdram_d[14]" SITE "J18"; +LOCATE COMP "sdram_d[15]" SITE "J17"; +IOBUF PORT "sdram_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_cke" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_csn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_wen" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_rasn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_casn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[8]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[9]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[10]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[11]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_a[12]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_ba[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_ba[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_dqm[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_dqm[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[8]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[9]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[10]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[11]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[12]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[13]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[14]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "sdram_d[15]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; + +# GPDI differential interface (Video) "gpdi" sheet +LOCATE COMP "gpdi_dp[0]" SITE "A16"; # Blue + +LOCATE COMP "gpdi_dn[0]" SITE "B16"; # Blue - +LOCATE COMP "gpdi_dp[1]" SITE "A14"; # Green + +LOCATE COMP "gpdi_dn[1]" SITE "C14"; # Green - +LOCATE COMP "gpdi_dp[2]" SITE "A12"; # Red + +LOCATE COMP "gpdi_dn[2]" SITE "A13"; # Red - +LOCATE COMP "gpdi_dp[3]" SITE "A17"; # Clock + +LOCATE COMP "gpdi_dn[3]" SITE "B18"; # Clock - +LOCATE COMP "gpdi_ethp" SITE "A19"; # Ethernet + +LOCATE COMP "gpdi_ethn" SITE "B20"; # Ethernet - +LOCATE COMP "gpdi_cec" SITE "A18"; +LOCATE COMP "gpdi_sda" SITE "B19"; # I2C shared with RTC +LOCATE COMP "gpdi_scl" SITE "E12"; # I2C shared with RTC C12->E12 +IOBUF PORT "gpdi_dp[0]" IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_dn[0]" IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_dp[1]" IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_dn[1]" IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_dp[2]" IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_dn[2]" IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_dp[3]" IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_dn[3]" IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_ethp" IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_ethn" IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_cec" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_sda" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "gpdi_scl" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; + +# GPIO (default single-ended) "gpio", "ram", "gpdi" sheet +# Physical connector pins: +# *** when FEMALE ANGLED (90 deg PMOD) soldered *** +# Jm_n- = Jm_n, Jm_n+ = Jm_n+1 +# example: J1_5- is J1_5 phsyical, J1_5+ is J1_6 physical +# *** when MALE VERTICAL soldered *** +# Jm_n+ = Jm_n, Jm_n- = Jm_n+1 +# example: J1_5+ is J1_5 physical, J1_5- is J1_6 physical +# Pins enumerated gp[0-27], gn[0-27]. +# With differential mode enabled on Lattice, +# gp[] (+) are used, gn[] (-) are ignored from design +# as they handle inverted signal by default. +# To enable differential, rename LVCMOS33->LVCMOS33D +# To enable clock i/o, add this (example): +#FREQUENCY PORT "gp[12]" 25.00 MHZ; +LOCATE COMP "gp[0]" SITE "B11"; # J1_5+ GP0 PCLK +LOCATE COMP "gn[0]" SITE "C11"; # J1_5- GN0 PCLK +LOCATE COMP "gp[1]" SITE "A10"; # J1_7+ GP1 PCLK +LOCATE COMP "gn[1]" SITE "A11"; # J1_7- GN1 PCLK +LOCATE COMP "gp[2]" SITE "A9"; # J1_9+ GP2 GR_PCLK +LOCATE COMP "gn[2]" SITE "B10"; # J1_9- GN2 GR_PCLK +LOCATE COMP "gp[3]" SITE "B9"; # J1_11+ GP3 +LOCATE COMP "gn[3]" SITE "C10"; # J1_11- GN3 +LOCATE COMP "gp[4]" SITE "A7"; # J1_13+ GP4 +LOCATE COMP "gn[4]" SITE "A8"; # J1_13- GN4 +LOCATE COMP "gp[5]" SITE "C8"; # J1_15+ GP5 +LOCATE COMP "gn[5]" SITE "B8"; # J1_15- GN5 +LOCATE COMP "gp[6]" SITE "C6"; # J1_17+ GP6 +LOCATE COMP "gn[6]" SITE "C7"; # J1_17- GN6 +IOBUF PORT "gp[0]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[0]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[1]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[1]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[2]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[2]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[3]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[3]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[4]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[4]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[5]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[5]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[6]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[6]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +LOCATE COMP "gp[7]" SITE "A6"; # J1_23+ GP7 +LOCATE COMP "gn[7]" SITE "B6"; # J1_23- GN7 +LOCATE COMP "gp[8]" SITE "A4"; # J1_25+ GP8 +LOCATE COMP "gn[8]" SITE "A5"; # J1_25- GN8 DIFF +LOCATE COMP "gp[9]" SITE "A2"; # J1_27+ GP9 DIFF +LOCATE COMP "gn[9]" SITE "B1"; # J1_27- GN9 DIFF +LOCATE COMP "gp[10]" SITE "C4"; # J1_29+ GP10 DIFF +LOCATE COMP "gn[10]" SITE "B4"; # J1_29- GN10 DIFF +LOCATE COMP "gp[11]" SITE "F4"; # J1_31+ GP11 DIFF WIFI_GPIO26 +LOCATE COMP "gn[11]" SITE "E3"; # J1_31- GN11 DIFF WIFI_GPIO25 +LOCATE COMP "gp[12]" SITE "G3"; # J1_33+ GP12 DIFF WIFI_GPIO33 PCLK +LOCATE COMP "gn[12]" SITE "F3"; # J1_33- GN12 DIFF WIFI_GPIO32 PCLK +LOCATE COMP "gp[13]" SITE "H4"; # J1_35+ GP13 DIFF WIFI_GPIO35 +LOCATE COMP "gn[13]" SITE "G5"; # J1_35- GN13 DIFF WIFI_GPIO34 +IOBUF PORT "gp[7]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[7]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[8]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[8]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[9]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[9]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[10]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[10]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[11]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[11]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[12]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[12]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[13]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[13]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +LOCATE COMP "gp[14]" SITE "U18"; # J2_5+ GP14 DIFF ADC1 +LOCATE COMP "gn[14]" SITE "U17"; # J2_5- GN14 DIFF ADC0 +LOCATE COMP "gp[15]" SITE "N17"; # J2_7+ GP15 DIFF ADC3 +LOCATE COMP "gn[15]" SITE "P16"; # J2_7- GN15 DIFF ADC2 +LOCATE COMP "gp[16]" SITE "N16"; # J2_9+ GP16 DIFF ADC5 +LOCATE COMP "gn[16]" SITE "M17"; # J2_9- GN16 DIFF ADC4 +LOCATE COMP "gp[17]" SITE "L16"; # J2_11+ GP17 DIFF ADC7 GR_PCLK +LOCATE COMP "gn[17]" SITE "L17"; # J2_11- GN17 DIFF ADC6 +LOCATE COMP "gp[18]" SITE "H18"; # J2_13+ GP18 DIFF +LOCATE COMP "gn[18]" SITE "H17"; # J2_13- GN18 DIFF +LOCATE COMP "gp[19]" SITE "F17"; # J2_15+ GP19 DIFF +LOCATE COMP "gn[19]" SITE "G18"; # J2_15- GN19 DIFF +LOCATE COMP "gp[20]" SITE "D18"; # J2_17+ GP20 DIFF +LOCATE COMP "gn[20]" SITE "E17"; # J2_17- GN20 DIFF +IOBUF PORT "gp[14]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[14]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[15]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[15]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[16]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[16]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[17]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[17]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[18]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[18]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[19]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[19]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[20]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[20]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +LOCATE COMP "gp[21]" SITE "C18"; # J2_23+ GP21 DIFF +LOCATE COMP "gn[21]" SITE "D17"; # J2_23- GN21 DIFF +LOCATE COMP "gp[22]" SITE "B15"; # J2_25+ GP22 +LOCATE COMP "gn[22]" SITE "C15"; # J2_25- GN22 +LOCATE COMP "gp[23]" SITE "B17"; # J2_27+ GP23 +LOCATE COMP "gn[23]" SITE "C17"; # J2_27- GN23 +LOCATE COMP "gp[24]" SITE "C16"; # J2_29+ GP24 +LOCATE COMP "gn[24]" SITE "D16"; # J2_29- GN24 +LOCATE COMP "gp[25]" SITE "D14"; # J2_31+ GP25 +LOCATE COMP "gn[25]" SITE "E14"; # J2_31- GN25 +LOCATE COMP "gp[26]" SITE "B13"; # J2_33+ GP26 +LOCATE COMP "gn[26]" SITE "C13"; # J2_33- GN26 +LOCATE COMP "gp[27]" SITE "D13"; # J2_35+ GP27 +LOCATE COMP "gn[27]" SITE "E13"; # J2_35- GN27 +IOBUF PORT "gp[21]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[21]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[22]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[22]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[23]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[23]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[24]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[24]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[25]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[25]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[26]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[26]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gp[27]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; +IOBUF PORT "gn[27]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8; + +## PROGRAMN (reload bitstream from FLASH, exit from bootloader) +# PCB v2.0.5 and higher +LOCATE COMP "user_programn" SITE "M4"; +IOBUF PORT "user_programn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; + +## SHUTDOWN "power", "ram" sheet (connected from PCB v1.7.5) +# on PCB v1.7 shutdown is not connected to FPGA +LOCATE COMP "shutdown" SITE "G16"; # FPGA receives +IOBUF PORT "shutdown" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; +#!/bin/bash + +case "$(uname -s)" in +MINGW*|CYGWIN*) +SILICE_DIR=`cygpath $SILICE_DIR` +BUILD_DIR=`cygpath $BUILD_DIR` +FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR` +FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE` +BOARD_DIR=`cygpath $BOARD_DIR` +;; +*) +esac + +echo "build script: SILICE_DIR = $SILICE_DIR" +echo "build script: BUILD_DIR = $BUILD_DIR" +echo "build script: BOARD_DIR = $BOARD_DIR" +echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR" +echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE" + +export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR +case "$(uname -s)" in +MINGW*) +export PYTHONHOME=/mingw64/bin +export PYTHONPATH=/mingw64/lib/python3.8/ +export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins +;; +*) +esac + +cd $BUILD_DIR + +rm build* +silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}" + +# exit ################### DEBUG DEBUG DEBUG + +yosys -p 'scratchpad -copy abc9.script.flow3 abc9.script; synth_ecp5 -abc9 -json build.json' build.v + +nextpnr-ecp5 --85k --package CABGA381 --freq 25 --json build.json --textcfg build.config --lpf $BOARD_DIR/ulx3s.lpf --timing-allow-fail + +sed -i '/.sysconfig/d' build.config + +ecppack --compress --svf-rowsize 100000 --svf build.svf build.config build.bit + +fujprog build.bit +{ + "name": "ulx3s", + "variants": [ + { + "name": "85k", + "framework" : "ulx3s.v", + "pins": [ + {"set" : "basic"}, + {"set" : "buttons","define" : "BUTTONS=1"}, + {"set" : "vga", "define" : "VGA=1"}, + {"set" : "oled", "define" : "OLED=1"}, + {"set" : "sdram", "define" : "SDRAM=1"}, + {"set" : "sdcard", "define" : "SDCARD=1"}, + {"set" : "hdmi", "define" : "HDMI=1"}, + {"set" : "gpio", "define" : "GPIO=1"}, + {"set" : "audio", "define" : "AUDIO=1"}, + {"set" : "uart", "define" : "UART=1"}, + {"set" : "uart2", "define" : "UART2=1"} + ], + "builders": [ + { + "builder" : "edalize", + "description": "Build using Edalize", + "tool": "trellis", + "tool_options": [ + { + "yosys_synth_options": ["-abc9"], + "nextpnr_options": ["--85k", "--freq 25", "--package CABGA381", "--timing-allow-fail"], + "pnr": "next" + } + ], + "bitstream" : "build.bit", + "constraints": [{"name": "ulx3s.lpf", "file_type": "LPF"}], + "program": [{"cmd" : "fujprog", "args" : "build.bit"}] + }, + { + "builder" : "shell", + "command" : "ulx3s.sh", + "description": "Custom shell scripts using yosys and nextpnr" + } + ] + } + ], + "pins": { + "basic": [ + { + "name": "leds", + "type": "uint8", + "io": "output" + } + ], + "buttons" : [ + { + "name": "btns", + "type": "uint7", + "io": "input" + } + ], + "audio" : [ + { + "name": "audio_l", + "type": "uint4", + "io": "output" + }, + { + "name": "audio_r", + "type": "uint4", + "io": "output" + } + ], + "oled": [ + { + "name": "oled_clk", + "type": "uint1", + "io": "output" + }, + { + "name": "oled_mosi", + "type": "uint1", + "io": "output" + }, + { + "name": "oled_dc", + "type": "uint1", + "io": "output" + }, + { + "name": "oled_resn", + "type": "uint1", + "io": "output" + }, + { + "name": "oled_csn", + "type": "uint1", + "io": "output" + } + ], + "sdcard": [ + { + "name": "sd_csn", + "type": "uint1", + "io": "output" + }, + { + "name": "sd_clk", + "type": "uint1", + "io": "output" + }, + { + "name": "sd_mosi", + "type": "uint1", + "io": "output" + }, + { + "name": "sd_miso", + "type": "uint1", + "io": "input" + } + ], + "sdram": [ + { + "name": "sdram_dq", + "type": "uint16", + "io": "inout" + }, + { + "name": "sdram_clk", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_cle", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_dqm", + "type": "uint2", + "io": "output" + }, + { + "name": "sdram_cs", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_we", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_cas", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_ras", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_ba", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_a", + "type": "uint1", + "io": "output" + } + ], + "hdmi": [ + { + "name": "gpdi_dq", + "type": "uint1", + "io": "output" + }, + { + "name": "gpdi_dn", + "type": "uint1", + "io": "output" + } + ], + "gpio": [ + { + "name": "gp", + "type": "uint28", + "io": "inout" + }, + { + "name": "gn", + "type": "uint28", + "io": "inout" + } + ], + "uart": [ + { + "name": "uart_tx", + "type": "uint1", + "io" : "output" + }, + { + "name": "uart_rx", + "type": "uint1", + "io" : "input" + } + ], + "uart2": [ + { + "name": "uart2_tx", + "type": "uint1", + "io" : "output" + }, + { + "name": "uart2_rx", + "type": "uint1", + "io" : "input" + } + ], + "vga": [ + { + "name": "vga_hs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_vs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_r", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_g", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_b", + "type": "uint6", + "io": "output" + } + ] + } +} +`define ICESTICK 1 +`default_nettype none +$$ICESTICK=1 +$$HARDWARE=1 +$$NUM_LEDS=5 +$$VGA=1 +$$color_depth=6 +$$color_max =63 +$$config['bram_wenable_width'] = 'data' +$$config['dualport_bram_wenable0_width'] = 'data' +$$config['dualport_bram_wenable1_width'] = 'data' +$$config['simple_dualport_bram_wenable0_width'] = 'data' +$$config['simple_dualport_bram_wenable1_width'] = 'data' + +module top( + output D1, + output D2, + output D3, + output D4, + output D5, +`ifdef OLED + output BR3, + output BR4, + output BR5, + output BR6, + output BR7, +`endif +`ifdef VGA + output PMOD1, // r0 + output PMOD2, // r1 + output PMOD3, // r2 + output PMOD4, // r3 + output PMOD8, // r4 + output PMOD9, // r5 + + output TR10, // g0 + output TR9, // g1 + output TR8, // g2 + output TR7, // g3 + output TR6, // g4 + output TR5, // g5 + + output BR10, // b0 + output BR9, // b1 + output BR8, // b2 + output BR7, // b3 + output BR6, // b4 + output BR5, // b5 + + output PMOD7, // hs + output PMOD10, // vs +`endif + input CLK + ); + +wire [4:0] __main_leds; + +`ifdef OLED +wire __main_oled_clk; +wire __main_oled_mosi; +wire __main_oled_csn; +wire __main_oled_resn; +wire __main_oled_dc; +`endif + +`ifdef VGA +wire __main_out_vga_hs; +wire __main_out_vga_vs; +wire __main_out_vga_v0; +wire [5:0] __main_out_vga_r; +wire [5:0] __main_out_vga_g; +wire [5:0] __main_out_vga_b; +`endif + +// the init sequence pauses for some cycles +// waiting for BRAM init to stabalize +// this is a known issue with ice40 FPGAs +// https://github.com/YosysHQ/icestorm/issues/76 + +reg ready = 0; +reg [31:0] RST_d; +reg [31:0] RST_q; + +always @* begin + RST_d = RST_q >> 1; +end + +always @(posedge CLK) begin + if (ready) begin + RST_q <= RST_d; + end else begin + ready <= 1; + RST_q <= 32'b11111111111111111111111111111111; + end +end + +wire run_main; +assign run_main = 1'b1; + +M_main __main( + .clock(CLK), + .reset(RST_d), + .out_leds(__main_leds), +`ifdef OLED + .out_oled_mosi(__main_oled_mosi), + .out_oled_clk(__main_oled_clk), + .out_oled_csn(__main_oled_csn), + .out_oled_dc(__main_oled_dc), + .out_oled_resn(__main_oled_resn), +`endif +`ifdef VGA + .out_video_hs(__main_out_vga_hs), + .out_video_vs(__main_out_vga_vs), + .out_video_r(__main_out_vga_r), + .out_video_g(__main_out_vga_g), + .out_video_b(__main_out_vga_b), +`endif + .in_run(run_main) +); + +assign D1 = __main_leds[0+:1]; +assign D2 = __main_leds[1+:1]; +assign D3 = __main_leds[2+:1]; +assign D4 = __main_leds[3+:1]; +assign D5 = __main_leds[4+:1]; + +// OLED + +`ifdef OLED + +assign BR3 = __main_oled_mosi; +assign BR4 = __main_oled_clk; +assign BR5 = __main_oled_csn; +assign BR6 = __main_oled_dc; +assign BR7 = __main_oled_resn; + +`endif + +// VGA + +`ifdef VGA + +assign PMOD1 = __main_out_vga_r[5+:1]; +assign PMOD2 = __main_out_vga_r[4+:1]; +assign PMOD3 = __main_out_vga_r[3+:1]; +assign PMOD4 = __main_out_vga_r[2+:1]; +assign PMOD8 = __main_out_vga_r[1+:1]; +assign PMOD9 = __main_out_vga_r[0+:1]; + +assign TR10 = __main_out_vga_g[5+:1]; +assign TR9 = __main_out_vga_g[4+:1]; +assign TR8 = __main_out_vga_g[3+:1]; +assign TR7 = __main_out_vga_g[2+:1]; +assign TR6 = __main_out_vga_g[1+:1]; +assign TR5 = __main_out_vga_g[0+:1]; + +assign BR10 = __main_out_vga_b[5+:1]; +assign BR9 = __main_out_vga_b[4+:1]; +assign BR8 = __main_out_vga_b[3+:1]; +assign BR7 = __main_out_vga_b[2+:1]; +assign BR6 = __main_out_vga_b[1+:1]; +assign BR5 = __main_out_vga_b[0+:1]; + +assign PMOD7 = __main_out_vga_hs; +assign PMOD10 = __main_out_vga_vs; + +`endif + + +endmodule +# ----------------------------------------------------------------------------- +#- Icestick constraint file (.pcf) +#- By Juan Gonzalez (Obijuan) +#- April - 2016 +#- GPL license +# ----------------------------------------------------------------------------- +# -- Pinout: https://github.com/Obijuan/open-fpga-verilog-tutorial/blob/master/tutorial/doc/images/icestick_pinout.png +# -- Guide: https://github.com/Obijuan/open-fpga-verilog-tutorial/blob/master/tutorial/doc/icestickusermanual.pdf + +# -- Icestick leds map +# +# D1 +# D4 D5 D2 +# D3 +# +# -- D1-D4: Red leds +# -- D5: green led + + +# ------------ Red leds ------------------------------------------------------ +set_io --warn-no-port D1 99 +set_io --warn-no-port D2 98 +set_io --warn-no-port D3 97 +set_io --warn-no-port D4 96 + +# ------------ Green led ----------------------------------------------------- +set_io --warn-no-port D5 95 + +# ------------ IrDA ---------------------------------------------------------- +set_io --warn-no-port IrDA_TX 105 +set_io --warn-no-port IrDA_RX 106 + +#-- SD = 0, enable IrDA +set_io --warn-no-port SD 107 + +# ------------ PMOD connector ------------------------------------------------ +# +# Pmod standar numeration (Oriented according the icestick, with the +# usb connector pointing to the left and IRda to the right) +# +# -------- +# | 12 6 | +# | 11 5 | +# | 10 4 | +# | 9 3 | +# | 8 2 | +# | 7 1 | < +# -------- +# +# FPGA pins: +# +# ---------- +# | 3V3 3V3 | +# | GND GND | +# | 91 81 | +# | 90 80 | +# | 88 79 | +# | 87 78 | < +# ---------- +# +set_io --warn-no-port PMOD1 78 +set_io --warn-no-port PMOD2 79 +set_io --warn-no-port PMOD3 80 +set_io --warn-no-port PMOD4 81 +set_io --warn-no-port PMOD7 87 +set_io --warn-no-port PMOD8 88 +set_io --warn-no-port PMOD9 90 +set_io --warn-no-port PMOD10 91 + +# ------------------------ EXPANSION I/O ------------------------------------ +# +# -- Numeration +# +# Top Row (TR): +# v +# -------------------------------- +# | 10 9 8 7 6 5 4 3 2 1 | +# -------------------------------- +# +# Bottom Row (BR): +# +# v +# -------------------------------- +# | 10 9 8 7 6 5 4 3 2 1 | +# -------------------------------- +# +# --- FPGA pins +# +# Top Row (TR) +# v +# -------------------------------------------------- +# | 119 118 117 116 115 114 113 112 GND 3v3 | +# -------------------------------------------------- +# +# +# Bottom Row (BR) +# +# v +# ------------------------------------------------- +# | 44 45 47 48 56 60 61 62 GND 3v3 | +# ------------------------------------------------- +# +# -- Top Row +set_io --warn-no-port TR3 112 +set_io --warn-no-port TR4 113 +set_io --warn-no-port TR5 114 +set_io --warn-no-port TR6 115 +set_io --warn-no-port TR7 116 +set_io --warn-no-port TR8 117 +set_io --warn-no-port TR9 118 +set_io --warn-no-port TR10 119 +# +# -- Bottom Row +set_io --warn-no-port BR3 62 +set_io --warn-no-port BR4 61 +set_io --warn-no-port BR5 60 +set_io --warn-no-port BR6 56 +set_io --warn-no-port BR7 48 +set_io --warn-no-port BR8 47 +set_io --warn-no-port BR9 45 +set_io --warn-no-port BR10 44 + +# -------------------------- SYSTEM CLOCK ------------------------------------ +set_io --warn-no-port CLK 21 + +# -------------------------- FTDI -------------------------------------------- +# --- FTDI 0: +set_io --warn-no-port RES 66 +set_io --warn-no-port DONE 65 +set_io --warn-no-port SS 71 +set_io --warn-no-port MISO 67 +set_io --warn-no-port MOSI 68 +set_io --warn-no-port SCK 70 +# +# --- FTDI 1: (Serial port) +set_io --warn-no-port DCD 1 +set_io --warn-no-port DSR 2 +set_io --warn-no-port DTR 3 +set_io --warn-no-port CTS 4 +set_io --warn-no-port RTS 7 +set_io --warn-no-port TX 8 +set_io --warn-no-port RX 9 +#!/bin/bash + +case "$(uname -s)" in +MINGW*|CYGWIN*) +SILICE_DIR=`cygpath $SILICE_DIR` +BUILD_DIR=`cygpath $BUILD_DIR` +FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR` +FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE` +BOARD_DIR=`cygpath $BOARD_DIR` +;; +*) +esac + +echo "build script: SILICE_DIR = $SILICE_DIR" +echo "build script: BUILD_DIR = $BUILD_DIR" +echo "build script: BOARD_DIR = $BOARD_DIR" +echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR" +echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE" + +export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR +case "$(uname -s)" in +MINGW*) +export PYTHONHOME=/mingw64/bin +export PYTHONPATH=/mingw64/lib/python3.8/ +export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins +;; +*) +esac + +cd $BUILD_DIR + +rm build* + +silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}" + +if ! type "nextpnr-ice40" > /dev/null; then + # try arachne-pnr instead + echo "nextpnr-ice40 not found, trying arachne-pnr instead" + yosys -q -p "synth_ice40 -blif build.blif" build.v + arachne-pnr -p $BOARD_DIR/icestick.pcf build.blif -o build.txt + icepack build.txt build.bin +else + yosys -p 'synth_ice40 -top top -json build.json' build.v + nextpnr-ice40 --hx1k --json build.json --pcf $BOARD_DIR/icestick.pcf --asc build.asc --package tq144 --freq 12 + icepack build.asc build.bin +fi + +iceprog build.bin +{ + "name": "icestick", + "variants": [ + { + "name" : "configurable", + "framework" : "icestick.v", + "pins" : [ + {"set" : "basic"}, + {"set" : "vga", "define" : "VGA=1"}, + {"set" : "oled", "define" : "OLED=1"} + ], + "builders": [ + { + "builder" : "edalize", + "description": "Build using Edalize", + "tool": "icestorm", + "tool_options": [ + { + "nextpnr_options": ["--hx1k", "--freq 12", "--package tq144", "--timing-allow-fail"], + "pnr": "next" + } + ], + "bitstream" : "build.bin", + "constraints": [{"name": "icestick.pcf", "file_type": "PCF"}], + "program": [{"cmd" : "iceprog", "args" : "build.bin"}] + }, + { + "builder" : "shell", + "command" : "icestick.sh", + "description": "Custom shell scripts using yosys and nextpnr" + } + ] + } + ], + "pins": { + "basic": [ + { + "name": "leds", + "type": "uint5", + "io": "output" + } + ], + "oled": [ + { + "name": "oled_clk", + "type": "uint1", + "io": "output" + }, + { + "name": "oled_mosi", + "type": "uint1", + "io": "output" + }, + { + "name": "oled_csn", + "type": "uint1", + "io": "output" + }, + { + "name": "oled_resn", + "type": "uint1", + "io": "output" + }, + { + "name": "oled_dc", + "type": "uint1", + "io": "output" + } + ], + "vga": [ + { + "name": "vga_hs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_vs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_r", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_g", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_b", + "type": "uint6", + "io": "output" + } + ] + } +} +#!/bin/bash + +case "$(uname -s)" in +MINGW*|CYGWIN*) +SILICE_DIR=`cygpath $SILICE_DIR` +BUILD_DIR=`cygpath $BUILD_DIR` +FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR` +FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE` +BOARD_DIR=`cygpath $BOARD_DIR` +;; +*) +esac + +echo "build script: SILICE_DIR = $SILICE_DIR" +echo "build script: BUILD_DIR = $BUILD_DIR" +echo "build script: BOARD_DIR = $BOARD_DIR" +echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR" +echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE" + +if hash make 2>/dev/null; then + export MAKE=make +else + export MAKE=mingw32-make +fi + +export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR + +if [[ -z "${VERILATOR_ROOT}" ]]; then +case "$(uname -s)" in +Linux) +unset VERILATOR_ROOT +;; +*) +export VERILATOR_ROOT=$SILICE_DIR/../tools/fpga-binutils/mingw64/ +;; +esac +echo "VERILATOR_ROOT is set to ${VERILATOR_ROOT}" +else +echo "VERILATOR_ROOT already defined, using its value" +fi + +u=$(echo "$1" | sed s:/:__:g | tr -d ".") + +echo "using directory $u" + +cd $BUILD_DIR + +silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}" + +if [[ -z "${VGA}" ]] && [[ -z "${SDRAM}" ]]; then +VERILATOR_LIB="verilator_bare" +else +VERILATOR_LIB="verilator_vga" +fi + +echo "using verilator framework $VERILATOR_LIB" + +verilator -Wno-PINMISSING -Wno-WIDTH -O3 -cc build.v --top-module top +cd obj_dir +$MAKE -f Vtop.mk +$MAKE -f Vtop.mk $SILICE_DIR/../frameworks/verilator/$VERILATOR_LIB.o verilated.o +g++ -O3 $SILICE_DIR/../frameworks/verilator/$VERILATOR_LIB.o verilated.o Vtop__ALL.a $SILICE_DIR/../frameworks/verilator/libverilator_silice.a -o ../run_simul +cd .. + +./run_simul +{ + "name": "verilator", + "variants": [ + { + "name" : "configurable", + "framework" : "verilator.v", + "pins" : [ + {"set" : "basic"}, + {"set" : "vga", "define" : "VGA=1"}, + {"set" : "sdram", "define" : "SDRAM=1"} + ], + "builders": [ + { + "builder" : "shell", + "command" : "verilator.sh", + "description": "Simulates with verilator" + } + ] + } + ], + "pins": { + "basic": [ + { + "name": "leds", + "type": "uint8", + "io": "output" + } + ], + "vga": [ + { + "name": "vga_hs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_vs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_r", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_g", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_b", + "type": "uint6", + "io": "output" + } + ], + "sdram": [ + { + "name": "sdram_clock", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_dq_i", + "type": "uint16", + "io": "input" + }, + { + "name": "sdram_dq_o", + "type": "uint16", + "io": "output" + }, + { + "name": "sdram_dq_en", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_cle", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_dqm", + "type": "uint2", + "io": "output" + }, + { + "name": "sdram_cs", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_we", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_cas", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_ras", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_ba", + "type": "uint1", + "io": "output" + }, + { + "name": "sdram_a", + "type": "uint1", + "io": "output" + } + ] + } +} +`define VERILATOR 1 +`define COLOR_DEPTH 6 +`define SDRAM_WORD_WIDTH 16 + +$$VERILATOR = 1 +$$NUM_LEDS = 8 +$$SIMULATION = 1 +$$color_depth = 6 +$$color_max = 63 + +`timescale 1ns / 1ps +`default_nettype none + +module top( + // SDRAM + output reg sdram_clock, + output reg sdram_cle, + output reg [1:0] sdram_dqm, + output reg sdram_cs, + output reg sdram_we, + output reg sdram_cas, + output reg sdram_ras, + output reg [1:0] sdram_ba, + output reg [12:0] sdram_a, + input [15:0] sdram_dq_i, + output reg [15:0] sdram_dq_o, + output reg sdram_dq_en, + // VGA + output video_clock, + output reg [`COLOR_DEPTH-1:0] video_r, + output reg [`COLOR_DEPTH-1:0] video_g, + output reg [`COLOR_DEPTH-1:0] video_b, + output video_hs, + output video_vs, + output [5:0] sdram_word_width, + output [4:0] video_color_depth, + input clk + ); + +// this is used by the verilator framework +// -> to know the output color depth +assign video_color_depth = `COLOR_DEPTH; +// -> to know the sdram word width +assign sdram_word_width = `SDRAM_WORD_WIDTH; + +wire __main_sdram_clock; +wire __main_sdram_cle; +wire [1:0] __main_sdram_dqm; +wire __main_sdram_cs; +wire __main_sdram_we; +wire __main_sdram_cas; +wire __main_sdram_ras; +wire [1:0] __main_sdram_ba; +wire [12:0] __main_sdram_a; +wire [15:0] __main_sdram_dq_o; +wire __main_sdram_dq_en; + +wire __main_video_clock; +wire [`COLOR_DEPTH-1:0] __main_video_r; +wire [`COLOR_DEPTH-1:0] __main_video_g; +wire [`COLOR_DEPTH-1:0] __main_video_b; +wire __main_video_hs; +wire __main_video_vs; + +wire [7:0] __main_leds; + +// reset + +reg ready = 0; +reg [3:0] RST_d; +reg [3:0] RST_q; + +always @* begin + RST_d = RST_q >> 1; +end + +always @(posedge clk) begin + if (ready) begin + RST_q <= RST_d; + end else begin + ready <= 1; + RST_q <= 4'b1111; + end +end + +// main + +wire run_main; +assign run_main = 1'b1; +wire done_main; + +M_main __main( + .clock(clk), + .reset(RST_d[0]), + .out_leds(__main_leds), +`ifdef SDRAM + .out_sdram_clock(__main_sdram_clock), + .out_sdram_cle(__main_sdram_cle), + .out_sdram_dqm(__main_sdram_dqm), + .out_sdram_cs(__main_sdram_cs), + .out_sdram_we(__main_sdram_we), + .out_sdram_cas(__main_sdram_cas), + .out_sdram_ras(__main_sdram_ras), + .out_sdram_ba(__main_sdram_ba), + .out_sdram_a(__main_sdram_a), + .in_sdram_dq_i(sdram_dq_i), + .out_sdram_dq_o(__main_sdram_dq_o), + .out_sdram_dq_en(__main_sdram_dq_en), +`endif +`ifdef VGA + .out_video_clock(__main_video_clock), + .out_video_r(__main_video_r), + .out_video_g(__main_video_g), + .out_video_b(__main_video_b), + .out_video_hs(__main_video_hs), + .out_video_vs(__main_video_vs), +`endif + .in_run(run_main), + .out_done(done_main) +); + +assign sdram_clock = __main_sdram_clock; +assign sdram_cle = __main_sdram_cle; +assign sdram_dqm = __main_sdram_dqm; +assign sdram_cs = __main_sdram_cs; +assign sdram_we = __main_sdram_we; +assign sdram_cas = __main_sdram_cas; +assign sdram_ras = __main_sdram_ras; +assign sdram_ba = __main_sdram_ba; +assign sdram_a = __main_sdram_a; +assign sdram_dq_o = __main_sdram_dq_o; +assign sdram_dq_en = __main_sdram_dq_en; + +assign video_clock = __main_video_clock; +assign video_r = __main_video_r; +assign video_g = __main_video_g; +assign video_b = __main_video_b; +assign video_hs = __main_video_hs; +assign video_vs = __main_video_vs; + +always @* begin + if (done_main && !RST_d[0]) $finish; +end + +endmodule +#!/bin/bash + +case "$(uname -s)" in +MINGW*|CYGWIN*) +SILICE_DIR=`cygpath $SILICE_DIR` +BUILD_DIR=`cygpath $BUILD_DIR` +FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR` +FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE` +BOARD_DIR=`cygpath $BOARD_DIR` +;; +*) +esac + +echo "build script: SILICE_DIR = $SILICE_DIR" +echo "build script: BUILD_DIR = $BUILD_DIR" +echo "build script: BOARD_DIR = $BOARD_DIR" +echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR" +echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE" + +export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR +export PYTHONHOME=/mingw64/bin +export PYTHONPATH=/mingw64/lib/python3.8/ +export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins + +cd $BUILD_DIR + +rm -rf build* *.rdf *.sty impl + +silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}" + +cat << EOF > build.tcl +prj_create -name "build" -impl "impl" -dev LIFCL-40-9BG400C +prj_set_impl_opt {include path} {""} +prj_add_source "build.v" -work work +prj_add_source "$BOARD_DIR/crosslink_nx_evn.pdc" -work work +prj_set_impl_opt top "top" +prj_save +prj_run Synthesis -impl impl -forceOne +prj_run Map -impl impl +prj_run PAR -impl impl +prj_run Export -impl impl -task Bitgen +prj_close +EOF + +radiantc build.tcl > toto.log 2>&1 # toto.log - French touch ;-) + +openFPGALoader impl/build_impl.bit +# ---------------------------------------------------------------------------- +# +# CrosslinkNX evn constraint file (.pdc) +# Link +# https://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/CrossLink-NXEvaluationBoard +# +# ---------------------------------------------------------------------------- + +# -------------------------- SYSTEM CLOCK ------------------------------------ +ldc_set_location -site {L13} [get_ports CLK] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports CLK] + +ldc_set_location -site {C12} [get_ports OSC_P] +ldc_set_location -site {C11} [get_ports OSC_N] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33D} [get_ports OSC_P] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33D} [get_ports OSC_N] + +# ------------------------------ UART ---------------------------------------- +ldc_set_location -site {F18} [get_ports RX] +ldc_set_location -site {F16} [get_ports TX] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33D} [get_ports OSC_P] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33D} [get_ports OSC_N] + +# ------------------------- LED ---------------------------------------------- +ldc_set_location -site {E17} [get_ports LED0] +ldc_set_location -site {F13} [get_ports LED1] +ldc_set_location -site {G13} [get_ports LED2] +ldc_set_location -site {F14} [get_ports LED3] +ldc_set_location -site {L16} [get_ports LED4] +ldc_set_location -site {L15} [get_ports LED5] +ldc_set_location -site {L20} [get_ports LED6] +ldc_set_location -site {L19} [get_ports LED7] +ldc_set_location -site {R17} [get_ports LED8] +ldc_set_location -site {R18} [get_ports LED9] +ldc_set_location -site {U20} [get_ports LED10] +ldc_set_location -site {T20} [get_ports LED11] +ldc_set_location -site {W20} [get_ports LED12] +ldc_set_location -site {V20} [get_ports LED13] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED0] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED1] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED2] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED3] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED4] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED5] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED6] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED7] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED8] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED9] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED10] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED11] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED12] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED13] + +# ------------------------- Button ------------------------------------------- +ldc_set_location -site {G14} [get_ports SW2] +ldc_set_location -site {G15} [get_ports SW3] +ldc_set_location -site {G19} [get_ports SW4] +ldc_set_location -site {E11} [get_ports SW5] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SW2] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SW3] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SW4] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SW5] + +# ----------------------- DIP Switch ----------------------------------------- +ldc_set_location -site {N14} [get_ports SWITCH0] +ldc_set_location -site {M14} [get_ports SWITCH1] +ldc_set_location -site {M16} [get_ports SWITCH2] +ldc_set_location -site {M15} [get_ports SWITCH3] +ldc_set_location -site {N15} [get_ports SWITCH4] +ldc_set_location -site {N16} [get_ports SWITCH5] +ldc_set_location -site {M17} [get_ports SWITCH6] +ldc_set_location -site {M18} [get_ports SWITCH7] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH0] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH1] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH2] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH3] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH4] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH5] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH6] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH7] + +# --------------------------- SPI Flash -------------------------------------- +ldc_set_location -site {} [get_ports FLASH_SCK] +ldc_set_location -site {} [get_ports FLASH_SSB] +ldc_set_location -site {} [get_ports FLASH_IO0] +ldc_set_location -site {} [get_ports FLASH_IO1] +ldc_set_location -site {} [get_ports FLASH_IO2] +ldc_set_location -site {} [get_ports FLASH_IO3] + +# ------------ PMOD0 connector --------- ------------------------------------- +ldc_set_location -site {D10} [get_ports PMOD0_1 ] +ldc_set_location -site {D9} [get_ports PMOD0_2 ] +ldc_set_location -site {D7} [get_ports PMOD0_3 ] +ldc_set_location -site {D8} [get_ports PMOD0_4 ] +ldc_set_location -site {D6} [get_ports PMOD0_7 ] +ldc_set_location -site {D5} [get_ports PMOD0_8 ] +ldc_set_location -site {D4} [get_ports PMOD0_9 ] +ldc_set_location -site {D3} [get_ports PMOD0_10] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_1 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_2 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_3 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_4 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_7 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_8 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_9 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_10] + +# ------------ PMOD1 connector ----------------------------------------------- +ldc_set_location -site {E10} [get_ports PMOD1_1 ] +ldc_set_location -site {E9} [get_ports PMOD1_2 ] +ldc_set_location -site {E7} [get_ports PMOD1_3 ] +ldc_set_location -site {E8} [get_ports PMOD1_4 ] +ldc_set_location -site {E4} [get_ports PMOD1_7 ] +ldc_set_location -site {E3} [get_ports PMOD1_8 ] +ldc_set_location -site {E2} [get_ports PMOD1_9 ] +ldc_set_location -site {F1} [get_ports PMOD1_10] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_1 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_2 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_3 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_4 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_7 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_8 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_9 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_10] + +# ------------ PMOD2 connector ----------------------------------------------- +ldc_set_location -site { J2} [get_ports PMOD2_1 ] +ldc_set_location -site { J1} [get_ports PMOD2_2 ] +ldc_set_location -site { K2} [get_ports PMOD2_3 ] +ldc_set_location -site { K1} [get_ports PMOD2_4 ] +ldc_set_location -site { K3} [get_ports PMOD2_7 ] +ldc_set_location -site { K4} [get_ports PMOD2_8 ] +ldc_set_location -site {D17} [get_ports PMOD2_9 ] +ldc_set_location -site {E18} [get_ports PMOD2_10] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_1 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_2 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_3 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_4 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_7 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_8 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_9 ] +ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_10] + +ldc_set_sysconfig {CONFIG_MODE=SPI_SERIAL MCCLK_FREQ=3.5} +`define CROSSLINKNX_EVN 1 +$$CROSSLINKNX_EVN=1 +$$HARDWARE=1 +$$NUM_LEDS=5 +$$VGA=1 +$$color_depth=6 +$$color_max =63 +$$config['bram_wenable_width'] = 'data' +$$config['dualport_bram_wenable0_width'] = 'data' +$$config['dualport_bram_wenable1_width'] = 'data' + +module top( + output LED0, + output LED1, + output LED2, + output LED3, + output LED4, +`ifdef VGA + output PMOD0_1, // r0 + output PMOD0_2, // r1 + output PMOD0_3, // r2 + output PMOD0_4, // r3 + + output PMOD0_7, // b0 + output PMOD0_8, // b1 + output PMOD0_9, // b2 + output PMOD0_10,// b3 + + output PMOD1_1, // g0 + output PMOD1_2, // g1 + output PMOD1_3, // g2 + output PMOD1_4, // g3 + + output PMOD1_7, // hs + output PMOD1_8, // vs +`endif + input CLK +); + +wire [4:0] __main_leds; + +// clock from design is used in case +// it relies on a PLL: in such cases +// we cannot use the clock fed into +// the PLL here +wire design_clk; + +`ifdef VGA +wire __main_out_vga_hs; +wire __main_out_vga_vs; +wire [5:0] __main_out_vga_r; +wire [5:0] __main_out_vga_g; +wire [5:0] __main_out_vga_b; +`endif + +BB u0_BB (.B(CLK), + .I(1'b0), + .T(1'b1), + .O(clk_s) +); + +reg ready = 0; +reg [31:0] RST_d; +reg [31:0] RST_q; + +always @* begin + RST_d = RST_q >> 1; +end + +always @(posedge design_clk) begin + if (ready) begin + RST_q <= RST_d; + end else begin + ready <= 1; + RST_q <= 32'b111111111111111111111111111111; + end +end + +wire run_main; +assign run_main = 1'b1; + +M_main __main( + .clock(clk_s), + .out_clock(design_clk), + .reset(RST_d[0]), + .out_leds(__main_leds), +`ifdef VGA + .out_video_hs(__main_out_vga_hs), + .out_video_vs(__main_out_vga_vs), + .out_video_r(__main_out_vga_r), + .out_video_g(__main_out_vga_g), + .out_video_b(__main_out_vga_b), +`endif + .in_run(run_main) +); + +assign LED0 = __main_leds[0+:1]; +assign LED1 = __main_leds[1+:1]; +assign LED2 = __main_leds[2+:1]; +assign LED3 = __main_leds[3+:1]; +assign LED4 = __main_leds[4+:1]; + +// VGA + +`ifdef VGA + +assign PMOD0_1 = __main_out_vga_r[2+:1]; +assign PMOD0_2 = __main_out_vga_r[3+:1]; +assign PMOD0_3 = __main_out_vga_r[4+:1]; +assign PMOD0_4 = __main_out_vga_r[5+:1]; + +assign PMOD0_7 = __main_out_vga_b[2+:1]; +assign PMOD0_8 = __main_out_vga_b[3+:1]; +assign PMOD0_9 = __main_out_vga_b[4+:1]; +assign PMOD0_10 = __main_out_vga_b[5+:1]; + +assign PMOD1_1 = __main_out_vga_g[2+:1]; +assign PMOD1_2 = __main_out_vga_g[3+:1]; +assign PMOD1_3 = __main_out_vga_g[4+:1]; +assign PMOD1_4 = __main_out_vga_g[5+:1]; + +assign PMOD1_7 = __main_out_vga_hs; +assign PMOD1_8 = __main_out_vga_vs; + +`endif + +endmodule +{ + "name": "crosslink_nx_evn", + "variants": [ + { + "name": "configurable", + "framework" : "crosslink_nx_evn.v", + "pins": [ + {"set" : "basic"}, + {"set" : "vga", "define" : "VGA=1"} + ], + "builders": [ + { + "builder" : "edalize", + "description": "Build using Edalize", + "tool": "radiant", + "tool_options": [ + { + "part": "LIFCL-40-9BG400C" + } + ], + "bitstream" : "impl/build_impl.bit", + "constraints": [{"name": "crosslink_nx_evn.pdc", "file_type": "PDC"}], + "program": [{"cmd" : "openFPGALoader", "args" : "impl/build_impl.bit"}] + }, + { + "builder" : "shell", + "command" : "crosslink_nx_evn.sh", + "description": "Custom shell scripts using lattice radiant" + } + ] + } + ], + "pins": { + "basic": [ + { + "name": "leds", + "type": "uint5", + "io": "output" + } + ], + "vga": [ + { + "name": "vga_hs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_vs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_r", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_g", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_b", + "type": "uint6", + "io": "output" + } + ] + } +} +`define MOJO 1 +$$MOJO=1 +$$HARDWARE = 1 +$$NUM_LEDS = 8 +$$NUM_BTNS = 1 +$$color_depth = 6 +$$color_max = 63 + +module top( + input rst_n, + input cclk, + output [7:0] leds, + output spi_miso, + input spi_ss, + input spi_mosi, + input spi_sck, + output [3:0] spi_channel, + input avr_tx, + output avr_rx, + input avr_rx_busy, + // SDRAM + output sdram_clk, + output sdram_cle, + output sdram_dqm, + output sdram_cs, + output sdram_we, + output sdram_cas, + output sdram_ras, + output [1:0] sdram_ba, + output [12:0] sdram_a, + inout [7:0] sdram_dq, + // HDMI + output [3:0] gpdi_dp, + output [3:0] gpdi_dn, + input clk + ); + +wire [7:0] __main_out_leds; + +wire __main_spi_miso; +wire __main_out_avr_rx; +wire [3:0] __main_out_spi_channel; + +wire __main_out_sdram_clk; +wire __main_out_sdram_cle; +wire __main_out_sdram_dqm; +wire __main_out_sdram_cs; +wire __main_out_sdram_we; +wire __main_out_sdram_cas; +wire __main_out_sdram_ras; +wire [1:0] __main_out_sdram_ba; +wire [12:0] __main_out_sdram_a; +wire [3:0] __main_out_hdmi1_tmds; +wire [3:0] __main_out_hdmi1_tmdsb; + +wire run_main; +assign run_main = 1'b1; + +M_main __main( + .reset(~rst_n), + .in_run(run_main), + .out_leds(__main_out_leds), +`ifdef SDRAM + .inout_sdram_dq(sdram_dq), + .out_sdram_clk(__main_out_sdram_clk), + .out_sdram_cle(__main_out_sdram_cle), + .out_sdram_dqm(__main_out_sdram_dqm), + .out_sdram_cs(__main_out_sdram_cs), + .out_sdram_we(__main_out_sdram_we), + .out_sdram_cas(__main_out_sdram_cas), + .out_sdram_ras(__main_out_sdram_ras), + .out_sdram_ba(__main_out_sdram_ba), + .out_sdram_a(__main_out_sdram_a), +`endif +`ifdef HDMI + .out_gpdi_dp (__main_out_gpdi_dp), + .out_gpdi_dn (__main_out_gpdi_dn), +`endif + .clock(clk) +); + +assign spi_miso = 1'bz; +assign avr_rx = 1'bz; +assign spi_channel = 4'bzzzz; + +assign leds = __main_out_leds; + +`ifdef SDRAM +assign sdram_clk = __main_out_sdram_clk; +assign sdram_cle = __main_out_sdram_cle; +assign sdram_dqm = __main_out_sdram_dqm; +assign sdram_cs = __main_out_sdram_cs; +assign sdram_we = __main_out_sdram_we; +assign sdram_cas = __main_out_sdram_cas; +assign sdram_ras = __main_out_sdram_ras; +assign sdram_ba = __main_out_sdram_ba; +assign sdram_a = __main_out_sdram_a; +`else +assign sdram_clk = 1'bz; +assign sdram_cle = 1'bz; +assign sdram_dqm = 1'bz; +assign sdram_cs = 1'bz; +assign sdram_we = 1'bz; +assign sdram_cas = 1'bz; +assign sdram_ras = 1'bz; +assign sdram_ba = 2'bzz; +assign sdram_a = 12'bzzzzzzzzzzzz; +`endif + +`ifdef HDMI +assign gpdi_dp = __main_out_gpdi_dp; +assign gpdi_dn = __main_out_gpdi_dn; +`else +assign gpdi_dp = 4'bzzzz; +assign gpdi_dn = 4'bzzzz; +`endif + +endmodule +NET "clk" TNM_NET = clk; +TIMESPEC TS_clk = PERIOD "clk" 50 MHz HIGH 50%; + +NET "clk" LOC = P56 | IOSTANDARD = LVTTL; +NET "rst_n" LOC = P38 | IOSTANDARD = LVTTL; + +NET "cclk" LOC = P70 | IOSTANDARD = LVTTL; + +NET "leds<0>" LOC = P134 | IOSTANDARD = LVTTL; +NET "leds<1>" LOC = P133 | IOSTANDARD = LVTTL; +NET "leds<2>" LOC = P132 | IOSTANDARD = LVTTL; +NET "leds<3>" LOC = P131 | IOSTANDARD = LVTTL; +NET "leds<4>" LOC = P127 | IOSTANDARD = LVTTL; +NET "leds<5>" LOC = P126 | IOSTANDARD = LVTTL; +NET "leds<6>" LOC = P124 | IOSTANDARD = LVTTL; +NET "leds<7>" LOC = P123 | IOSTANDARD = LVTTL; + +NET "spi_mosi" LOC = P44 | IOSTANDARD = LVTTL; +NET "spi_miso" LOC = P45 | IOSTANDARD = LVTTL; +NET "spi_ss" LOC = P48 | IOSTANDARD = LVTTL; +NET "spi_sck" LOC = P43 | IOSTANDARD = LVTTL; +NET "spi_channel<0>" LOC = P46 | IOSTANDARD = LVTTL; +NET "spi_channel<1>" LOC = P61 | IOSTANDARD = LVTTL; +NET "spi_channel<2>" LOC = P62 | IOSTANDARD = LVTTL; +NET "spi_channel<3>" LOC = P65 | IOSTANDARD = LVTTL; + +NET "avr_tx" LOC = P55 | IOSTANDARD = LVTTL; +NET "avr_rx" LOC = P59 | IOSTANDARD = LVTTL; +NET "avr_rx_busy" LOC = P39 | IOSTANDARD = LVTTL; + +NET "sdram_clk" LOC = P29 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_cle" LOC = P30 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_dqm" LOC = P74 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_cs" LOC = P84 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_we" LOC = P81 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_cas" LOC = P82 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_ras" LOC = P83 | IOSTANDARD = LVTTL | SLEW = FAST; + +NET "sdram_ba<0>" LOC = P85 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_ba<1>" LOC = P87 | IOSTANDARD = LVTTL | SLEW = FAST; + +NET "sdram_a<0>" LOC = P101 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<1>" LOC = P102 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<2>" LOC = P104 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<3>" LOC = P105 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<4>" LOC = P5 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<5>" LOC = P6 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<6>" LOC = P7 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<7>" LOC = P8 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<8>" LOC = P9 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<9>" LOC = P10 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<10>" LOC = P88 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<11>" LOC = P27 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_a<12>" LOC = P26 | IOSTANDARD = LVTTL | SLEW = FAST; + +NET "sdram_dq<0>" LOC = P75 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_dq<1>" LOC = P78 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_dq<2>" LOC = P79 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_dq<3>" LOC = P80 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_dq<4>" LOC = P34 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_dq<5>" LOC = P35 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_dq<6>" LOC = P40 | IOSTANDARD = LVTTL | SLEW = FAST; +NET "sdram_dq<7>" LOC = P41 | IOSTANDARD = LVTTL | SLEW = FAST; + +NET "gpdi_dp(3)" LOC = "P144" |IOSTANDARD = TMDS_33 | CLOCK_DEDICATED_ROUTE = FALSE ; # Clock +NET "gpdi_dn(3)" LOC = "P143" |IOSTANDARD = TMDS_33 | CLOCK_DEDICATED_ROUTE = FALSE ; +NET "gpdi_dp(2)" LOC = "P138" |IOSTANDARD = TMDS_33 ; # Red +NET "gpdi_dn(2)" LOC = "P137" |IOSTANDARD = TMDS_33 ; +NET "gpdi_dp(1)" LOC = "P140" |IOSTANDARD = TMDS_33 ; # Green +NET "gpdi_dn(1)" LOC = "P139" |IOSTANDARD = TMDS_33 ; +NET "gpdi_dp(0)" LOC = "P142" |IOSTANDARD = TMDS_33 ; # Blue +NET "gpdi_dn(0)" LOC = "P141" |IOSTANDARD = TMDS_33 ; +{ + "name": "mojov3", + "variants": [ + { + "name": "configurable", + "framework" : "mojov3.v", + "pins": [ + {"set" : "basic"} + ], + "builders": [ + { + "builder" : "edalize", + "description": "Build using Edalize", + "tool": "ise", + "tool_options": [ + { + "family": "spartan6", + "device": "xc6slx9", + "package": "tqg144", + "speed" : -2 + } + ], + "toplevel" : "top", + "bitstream" : "top.bin", + "constraints": [ + {"name": "mojov3.ucf", "file_type": "UCF"} + ], + "program": [ + {"cmd" : "promgen", "args" : "-u 0 top.bit -p bin -spi -w"}, + {"cmd" : "printf", "args" : "\"\\n\\nThe programming file has been generated in BUILD_mojov3/top.bin, please use Mojo Loader to program your board\\n\\n\""}, + {"cmd" : "mojo-loader", "args" : "-b top.bin"} + ] + } + ] + } + ], + "pins": { + "basic": [ + { + "name": "leds", + "type": "uint8", + "io" : "output" + } + ] + } +} +`define ICARUS 1 +$$ICARUS = 1 +$$SIMULATION = 1 +$$NUM_LEDS = 8 +$$color_depth = 6 +$$color_max = 63 +$$config['bram_wenable_width'] = 'data' +$$config['dualport_bram_wenable0_width'] = 'data' +$$config['dualport_bram_wenable1_width'] = 'data' + +`timescale 1ns / 1ps + +module top; + +reg clk; +reg rst_n; + +wire [7:0] __main_leds; + +`ifdef VGA +wire __main_video_clock; +wire __main_video_hs; +wire __main_video_vs; +wire [5:0] __main_video_r; +wire [5:0] __main_video_g; +wire [5:0] __main_video_b; +`endif + +`ifdef UART +wire __main_uart_tx; +wire __main_uart_rx = 0; +`endif + +`ifdef HDMI +wire [3:0] __main_out_gpdi_dp; +wire [3:0] __main_out_gpdi_dn; +`endif + +initial begin + clk = 1'b0; + rst_n = 1'b0; + $display("icarus framework started"); + $dumpfile("icarus.fst"); +`ifdef DUMP_TOP_ONLY + $dumpvars(1,top); // dump only top (faster and smaller) +`else + $dumpvars(0,top); // dump all (for full debugging) +`endif +`ifdef CLOCK_25MHz + // generate a 25 MHz clock + repeat(4) #20 clk = ~clk; + rst_n = 1'b1; + forever #20 clk = ~clk; +`else + // generate a 100 MHz clock + repeat(4) #5 clk = ~clk; + rst_n = 1'b1; + forever #5 clk = ~clk; +`endif +end + +reg ready = 0; +reg [3:0] RST_d; +reg [3:0] RST_q; + +always @* begin + RST_d = RST_q >> 1; +end + +always @(posedge clk) begin + if (ready) begin + RST_q <= RST_d; + end else begin + ready <= 1; + RST_q <= 4'b1111; + end +end + +wire run_main; +assign run_main = 1'b1; +wire done_main; + +M_main __main( + .clock(clk), + .reset(RST_d[0]), + .out_leds(__main_leds), +`ifdef VGA + .out_video_clock(__main_video_clock), + .out_video_r(__main_video_r), + .out_video_g(__main_video_g), + .out_video_b(__main_video_b), + .out_video_hs(__main_video_hs), + .out_video_vs(__main_video_vs), +`endif +`ifdef UART + .out_uart_tx(__main_uart_tx), + .in_uart_rx(__main_uart_rx), +`endif +`ifdef HDMI + .out_gpdi_dp (__main_out_gpdi_dp), + .out_gpdi_dn (__main_out_gpdi_dn), +`endif + .in_run(run_main), + .out_done(done_main) +); + +always @* begin + if (done_main && !RST_d[0]) $finish; +end + +endmodule + +#!/bin/bash + +case "$(uname -s)" in +MINGW*|CYGWIN*) +SILICE_DIR=`cygpath $SILICE_DIR` +BUILD_DIR=`cygpath $BUILD_DIR` +FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR` +FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE` +BOARD_DIR=`cygpath $BOARD_DIR` +;; +*) +esac + +echo "build script: SILICE_DIR = $SILICE_DIR" +echo "build script: BUILD_DIR = $BUILD_DIR" +echo "build script: BOARD_DIR = $BOARD_DIR" +echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR" +echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE" + +export PATH=$PATH:$SILICE_DIR:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/ +case "$(uname -s)" in +MINGW*) +export PYTHONHOME=/mingw64/bin +export PYTHONPATH=/mingw64/lib/python3.8/ +export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins +;; +*) +esac + +cd $BUILD_DIR + +rm build* icarus.fst icarus.fst.hier + +silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}" + +iverilog -o build build.v +vvp build -fst + +gtkwave icarus.fst +{ + "name": "icarus", + "variants": [ + { + "name" : "configurable", + "framework" : "icarus.v", + "pins" : [ + {"set" : "basic"}, + {"set" : "vga", "define" : "VGA=1"}, + {"set" : "hdmi", "define" : "HDMI=1"}, + {"set" : "uart", "define" : "UART=1"}, + {"set" : "top_only", "define" : "DUMP_TOP_ONLY=1"} + ], + "builders": [ + { + "builder" : "shell", + "command" : "icarus.sh", + "description": "Simulates with icarus and opens gtkwave for visualization" + } + ] + } + ], + "pins": { + "basic": [ + { + "name": "leds", + "type": "uint8", + "io": "output" + } + ], + "uart": [ + { + "name": "uart_tx", + "type": "uint1", + "io" : "output" + }, + { + "name": "uart_rx", + "type": "uint1", + "io" : "input" + } + ], + "vga": [ + { + "name": "vga_hs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_vs", + "type": "uint1", + "io": "output" + }, + { + "name": "vga_r", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_g", + "type": "uint6", + "io": "output" + }, + { + "name": "vga_b", + "type": "uint6", + "io": "output" + } + ], + "hdmi": [ + { + "name": "gpdi_dq", + "type": "uint1", + "io": "output" + }, + { + "name": "gpdi_dn", + "type": "uint1", + "io": "output" + } + ] + } +} diff --git a/src/worker/fs/fsSilice.js b/src/worker/fs/fsSilice.js new file mode 100644 index 00000000..2254f1bc --- /dev/null +++ b/src/worker/fs/fsSilice.js @@ -0,0 +1,213 @@ + + var Module = typeof Module !== 'undefined' ? Module : {}; + + if (!Module.expectedDataFileDownloads) { + Module.expectedDataFileDownloads = 0; + } + Module.expectedDataFileDownloads++; + (function() { + var loadPackage = function(metadata) { + + var PACKAGE_PATH; + if (typeof window === 'object') { + PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/'); + } else if (typeof location !== 'undefined') { + // worker + PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/'); + } else { + throw 'using preloaded data can only be done on a web page or in a web worker'; + } + var PACKAGE_NAME = '/home/hugg/8bitworkshop-compilers/output/fs/fsSilice.data'; + var REMOTE_PACKAGE_BASE = 'fsSilice.data'; + if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) { + Module['locateFile'] = Module['locateFilePackage']; + err('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)'); + } + var REMOTE_PACKAGE_NAME = Module['locateFile'] ? Module['locateFile'](REMOTE_PACKAGE_BASE, '') : REMOTE_PACKAGE_BASE; + + var REMOTE_PACKAGE_SIZE = metadata['remote_package_size']; + var PACKAGE_UUID = metadata['package_uuid']; + + function fetchRemotePackage(packageName, packageSize, callback, errback) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', packageName, true); + xhr.responseType = 'arraybuffer'; + xhr.onprogress = function(event) { + var url = packageName; + var size = packageSize; + if (event.total) size = event.total; + if (event.loaded) { + if (!xhr.addedTotal) { + xhr.addedTotal = true; + if (!Module.dataFileDownloads) Module.dataFileDownloads = {}; + Module.dataFileDownloads[url] = { + loaded: event.loaded, + total: size + }; + } else { + Module.dataFileDownloads[url].loaded = event.loaded; + } + var total = 0; + var loaded = 0; + var num = 0; + for (var download in Module.dataFileDownloads) { + var data = Module.dataFileDownloads[download]; + total += data.total; + loaded += data.loaded; + num++; + } + total = Math.ceil(total * Module.expectedDataFileDownloads/num); + if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')'); + } else if (!Module.dataFileDownloads) { + if (Module['setStatus']) Module['setStatus']('Downloading data...'); + } + }; + xhr.onerror = function(event) { + throw new Error("NetworkError for: " + packageName); + } + xhr.onload = function(event) { + if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + var packageData = xhr.response; + callback(packageData); + } else { + throw new Error(xhr.statusText + " : " + xhr.responseURL); + } + }; + xhr.send(null); + }; + + function handleError(error) { + console.error('package error:', error); + }; + + var fetchedCallback = null; + var fetched = Module['getPreloadedPackage'] ? Module['getPreloadedPackage'](REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE) : null; + + if (!fetched) fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, function(data) { + if (fetchedCallback) { + fetchedCallback(data); + fetchedCallback = null; + } else { + fetched = data; + } + }, handleError); + + function runWithFS() { + + function assert(check, msg) { + if (!check) throw msg + new Error().stack; + } + Module['FS_createPath']('/', 'frameworks', true, true); +Module['FS_createPath']('/frameworks', 'templates', true, true); +Module['FS_createPath']('/frameworks', 'libraries', true, true); +Module['FS_createPath']('/frameworks', 'verilator', true, true); +Module['FS_createPath']('/frameworks', 'boards', true, true); +Module['FS_createPath']('/frameworks/boards', 'icebreaker', true, true); +Module['FS_createPath']('/frameworks/boards', 'orangecrab', true, true); +Module['FS_createPath']('/frameworks/boards', 'de10nano', true, true); +Module['FS_createPath']('/frameworks/boards', 'techgraph', true, true); +Module['FS_createPath']('/frameworks/boards', '8bitworkshop', true, true); +Module['FS_createPath']('/frameworks/boards', 'fomu', true, true); +Module['FS_createPath']('/frameworks/boards', 'ulx3s', true, true); +Module['FS_createPath']('/frameworks/boards', 'icestick', true, true); +Module['FS_createPath']('/frameworks/boards', 'verilator', true, true); +Module['FS_createPath']('/frameworks/boards', 'crosslink_nx_evn', true, true); +Module['FS_createPath']('/frameworks/boards', 'mojov3', true, true); +Module['FS_createPath']('/frameworks/boards', 'icarus', true, true); + + /** @constructor */ + function DataRequest(start, end, audio) { + this.start = start; + this.end = end; + this.audio = audio; + } + DataRequest.prototype = { + requests: {}, + open: function(mode, name) { + this.name = name; + this.requests[name] = this; + Module['addRunDependency']('fp ' + this.name); + }, + send: function() {}, + onload: function() { + var byteArray = this.byteArray.subarray(this.start, this.end); + this.finish(byteArray); + }, + finish: function(byteArray) { + var that = this; + + Module['FS_createDataFile'](this.name, null, byteArray, true, true, true); // canOwn this data in the filesystem, it is a slide into the heap that will never change + Module['removeRunDependency']('fp ' + that.name); + + this.requests[this.name] = null; + } + }; + + var files = metadata['files']; + for (var i = 0; i < files.length; ++i) { + new DataRequest(files[i]['start'], files[i]['end'], files[i]['audio']).open('GET', files[i]['filename']); + } + + + function processPackageData(arrayBuffer) { + assert(arrayBuffer, 'Loading data file failed.'); + assert(arrayBuffer instanceof ArrayBuffer, 'bad input to processPackageData'); + var byteArray = new Uint8Array(arrayBuffer); + var curr; + + // Reuse the bytearray from the XHR as the source for file reads. + DataRequest.prototype.byteArray = byteArray; + + var files = metadata['files']; + for (var i = 0; i < files.length; ++i) { + DataRequest.prototype.requests[files[i].filename].onload(); + } + Module['removeRunDependency']('datafile_/home/hugg/8bitworkshop-compilers/output/fs/fsSilice.data'); + + }; + Module['addRunDependency']('datafile_/home/hugg/8bitworkshop-compilers/output/fs/fsSilice.data'); + + if (!Module.preloadResults) Module.preloadResults = {}; + + Module.preloadResults[PACKAGE_NAME] = {fromCache: false}; + if (fetched) { + processPackageData(fetched); + fetched = null; + } else { + fetchedCallback = processPackageData; + } + + } + if (Module['calledRun']) { + runWithFS(); + } else { + if (!Module['preRun']) Module['preRun'] = []; + Module["preRun"].push(runWithFS); // FS is not initialized yet, wait for it + } + + Module['removeRunDependency']('fsSilice.js.metadata'); + } + + function runMetaWithFS() { + Module['addRunDependency']('fsSilice.js.metadata'); + var REMOTE_METADATA_NAME = Module['locateFile'] ? Module['locateFile']('fsSilice.js.metadata', '') : 'fsSilice.js.metadata'; + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function() { + if (xhr.readyState === 4 && xhr.status === 200) { + loadPackage(JSON.parse(xhr.responseText)); + } + } + xhr.open('GET', REMOTE_METADATA_NAME, true); + xhr.overrideMimeType('application/json'); + xhr.send(null); + } + + if (Module['calledRun']) { + runMetaWithFS(); + } else { + if (!Module['preRun']) Module['preRun'] = []; + Module["preRun"].push(runMetaWithFS); + } + + })(); + \ No newline at end of file diff --git a/src/worker/fs/fsSilice.js.metadata b/src/worker/fs/fsSilice.js.metadata new file mode 100644 index 00000000..6f526cc2 --- /dev/null +++ b/src/worker/fs/fsSilice.js.metadata @@ -0,0 +1 @@ +{"files":[{"filename":"/frameworks/templates/dualport_bram_altera.v.in","start":0,"end":1092,"audio":0},{"filename":"/frameworks/templates/bram_generic.v.in","start":1092,"end":1660,"audio":0},{"filename":"/frameworks/templates/dualport_bram_generic.v.in","start":1660,"end":2692,"audio":0},{"filename":"/frameworks/templates/simple_dualport_bram_generic.v.in","start":2692,"end":3425,"audio":0},{"filename":"/frameworks/templates/brom_generic.v.in","start":3425,"end":3779,"audio":0},{"filename":"/frameworks/libraries/memory_ports.ice","start":3779,"end":4751,"audio":0},{"filename":"/frameworks/verilator/VgaChip.cpp","start":4751,"end":5644,"audio":0},{"filename":"/frameworks/verilator/video_out.cpp","start":5644,"end":13267,"audio":0},{"filename":"/frameworks/verilator/verilator_bare.cpp","start":13267,"end":14064,"audio":0},{"filename":"/frameworks/verilator/verilator_vga.cpp","start":14064,"end":16635,"audio":0},{"filename":"/frameworks/verilator/sdr_sdram.h","start":16635,"end":23554,"audio":0},{"filename":"/frameworks/verilator/sdr_sdram.cpp","start":23554,"end":84598,"audio":0},{"filename":"/frameworks/verilator/VgaChip.h","start":84598,"end":85371,"audio":0},{"filename":"/frameworks/verilator/CMakeLists.txt","start":85371,"end":86531,"audio":0},{"filename":"/frameworks/verilator/video_out.h","start":86531,"end":88965,"audio":0},{"filename":"/frameworks/boards/boards.json","start":88965,"end":89462,"audio":0},{"filename":"/frameworks/boards/icebreaker/icebreaker.sh","start":89462,"end":90534,"audio":0},{"filename":"/frameworks/boards/icebreaker/icebreaker.pcf","start":90534,"end":92627,"audio":0},{"filename":"/frameworks/boards/icebreaker/board.json","start":92627,"end":94616,"audio":0},{"filename":"/frameworks/boards/icebreaker/icebreaker.v","start":94616,"end":97259,"audio":0},{"filename":"/frameworks/boards/orangecrab/orangecrab.sh","start":97259,"end":98456,"audio":0},{"filename":"/frameworks/boards/orangecrab/orangecrab.v","start":98456,"end":99148,"audio":0},{"filename":"/frameworks/boards/orangecrab/board.json","start":99148,"end":100338,"audio":0},{"filename":"/frameworks/boards/orangecrab/pinout.lpf","start":100338,"end":102370,"audio":0},{"filename":"/frameworks/boards/de10nano/pins.tcl","start":102370,"end":109177,"audio":0},{"filename":"/frameworks/boards/de10nano/board.json","start":109177,"end":112617,"audio":0},{"filename":"/frameworks/boards/de10nano/build.sdc","start":112617,"end":113425,"audio":0},{"filename":"/frameworks/boards/de10nano/de10nano.v","start":113425,"end":117659,"audio":0},{"filename":"/frameworks/boards/techgraph/techgraph.sh","start":117659,"end":118661,"audio":0},{"filename":"/frameworks/boards/techgraph/techgraph.v","start":118661,"end":119127,"audio":0},{"filename":"/frameworks/boards/techgraph/board.json","start":119127,"end":119644,"audio":0},{"filename":"/frameworks/boards/8bitworkshop/8bitworkshop.v","start":119644,"end":120743,"audio":0},{"filename":"/frameworks/boards/8bitworkshop/8bitworkshop.sh","start":120743,"end":122394,"audio":0},{"filename":"/frameworks/boards/8bitworkshop/board.json","start":122394,"end":123719,"audio":0},{"filename":"/frameworks/boards/fomu/board.json","start":123719,"end":125167,"audio":0},{"filename":"/frameworks/boards/fomu/fomu-hacker.pcf","start":125167,"end":125796,"audio":0},{"filename":"/frameworks/boards/fomu/fomu.v","start":125796,"end":129036,"audio":0},{"filename":"/frameworks/boards/fomu/fomu.sh","start":129036,"end":130320,"audio":0},{"filename":"/frameworks/boards/ulx3s/ulx3s.v","start":130320,"end":136526,"audio":0},{"filename":"/frameworks/boards/ulx3s/ulx3s.lpf","start":136526,"end":159345,"audio":0},{"filename":"/frameworks/boards/ulx3s/ulx3s.sh","start":159345,"end":160626,"audio":0},{"filename":"/frameworks/boards/ulx3s/board.json","start":160626,"end":165574,"audio":0},{"filename":"/frameworks/boards/icestick/icestick.v","start":165574,"end":169049,"audio":0},{"filename":"/frameworks/boards/icestick/icestick.pcf","start":169049,"end":173089,"audio":0},{"filename":"/frameworks/boards/icestick/icestick.sh","start":173089,"end":174461,"audio":0},{"filename":"/frameworks/boards/icestick/board.json","start":174461,"end":176533,"audio":0},{"filename":"/frameworks/boards/verilator/verilator.sh","start":176533,"end":178176,"audio":0},{"filename":"/frameworks/boards/verilator/board.json","start":178176,"end":180401,"audio":0},{"filename":"/frameworks/boards/verilator/verilator.v","start":180401,"end":183909,"audio":0},{"filename":"/frameworks/boards/crosslink_nx_evn/crosslink_nx_evn.sh","start":183909,"end":185243,"audio":0},{"filename":"/frameworks/boards/crosslink_nx_evn/crosslink_nx_evn.pdc","start":185243,"end":192490,"audio":0},{"filename":"/frameworks/boards/crosslink_nx_evn/crosslink_nx_evn.v","start":192490,"end":194998,"audio":0},{"filename":"/frameworks/boards/crosslink_nx_evn/board.json","start":194998,"end":196456,"audio":0},{"filename":"/frameworks/boards/mojov3/mojov3.v","start":196456,"end":199292,"audio":0},{"filename":"/frameworks/boards/mojov3/mojov3.ucf","start":199292,"end":202847,"audio":0},{"filename":"/frameworks/boards/mojov3/board.json","start":202847,"end":203956,"audio":0},{"filename":"/frameworks/boards/icarus/icarus.v","start":203956,"end":205986,"audio":0},{"filename":"/frameworks/boards/icarus/icarus.sh","start":205986,"end":206936,"audio":0},{"filename":"/frameworks/boards/icarus/board.json","start":206936,"end":208550,"audio":0}],"remote_package_size":208550,"package_uuid":"98d85071-8779-43bb-abac-62cde992bbc4"} \ No newline at end of file diff --git a/src/worker/lib/verilog/8bitworkshop.v b/src/worker/lib/verilog/8bitworkshop.v new file mode 100755 index 00000000..ad824346 --- /dev/null +++ b/src/worker/lib/verilog/8bitworkshop.v @@ -0,0 +1,60 @@ +/* for Silice: https://github.com/sylefeb/Silice */ + +`define VERILATOR 1 +`define COLOR_DEPTH 8 + +/*verilator lint_off pinmissing */ +/*verilator lint_off undriven */ +/*verilator lint_off width */ + +$$VERILATOR = 1 +$$NUM_LEDS = 0 +$$SIMULATION = 1 +$$color_depth = 8 +$$color_max = 255 + +`timescale 1ns / 1ps +`default_nettype none + +module top( +`ifdef NTSC + // NTSC + output reg [31:0] rgb, + output hsync, + output vsync, +`endif + input clk, + input reset + ); + +wire [7:0] __main_video_r; +wire [7:0] __main_video_g; +wire [7:0] __main_video_b; +wire __main_video_hs; +wire __main_video_vs; + +// main + +wire run_main; +assign run_main = 1'b1; +wire done_main; + +M_main __main( + .clock(clk), + .reset(reset), +`ifdef NTSC + .out_video_r(__main_video_r), + .out_video_g(__main_video_g), + .out_video_b(__main_video_b), + .out_video_hs(__main_video_hs), + .out_video_vs(__main_video_vs), +`endif + .in_run(run_main), + .out_done(done_main) +); + +assign rgb = {8'hff, __main_video_b, __main_video_g, __main_video_r}; +assign hsync = __main_video_hs; +assign vsync = __main_video_vs; + +endmodule diff --git a/src/worker/wasm/silice.js b/src/worker/wasm/silice.js new file mode 100644 index 00000000..85f2d6f0 --- /dev/null +++ b/src/worker/wasm/silice.js @@ -0,0 +1,21 @@ + +var silice = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( +function(silice) { + silice = silice || {}; + +var Module=typeof silice!=="undefined"?silice:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!=="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function alignMemory(size,factor){if(!factor)factor=STACK_ALIGN;return Math.ceil(size/factor)*factor}var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heap[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8Array(str,HEAP8,ret,size);return ret}function allocateUTF8OnStack(str){var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8Array(str,HEAP8,ret,size);return ret}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();TTY.init();callRuntimeCallbacks(__ATINIT__)}function preMain(){FS.ignorePermissions=false;callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="silice.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return Promise.resolve().then(getBinary)}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["Ia"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["Ja"];removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync().catch(readyPromiseReject);return{}}var tempDouble;var tempI64;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){wasmTable.get(func)()}else{wasmTable.get(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var _emscripten_get_now;if(ENVIRONMENT_IS_NODE){_emscripten_get_now=function(){var t=process["hrtime"]();return t[0]*1e3+t[1]/1e6}}else if(typeof dateNow!=="undefined"){_emscripten_get_now=dateNow}else _emscripten_get_now=function(){return performance.now()};var _emscripten_get_now_is_monotonic=true;function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}function _clock_gettime(clk_id,tp){var now;if(clk_id===0){now=Date.now()}else if((clk_id===1||clk_id===4)&&_emscripten_get_now_is_monotonic){now=_emscripten_get_now()}else{setErrNo(28);return-1}HEAP32[tp>>2]=now/1e3|0;HEAP32[tp+4>>2]=now%1e3*1e3*1e3|0;return 0}function ___clock_gettime(a0,a1){return _clock_gettime(a0,a1)}var ExceptionInfoAttrs={DESTRUCTOR_OFFSET:0,REFCOUNT_OFFSET:4,TYPE_OFFSET:8,CAUGHT_OFFSET:12,RETHROWN_OFFSET:13,SIZE:16};function ___cxa_allocate_exception(size){return _malloc(size+ExceptionInfoAttrs.SIZE)+ExceptionInfoAttrs.SIZE}function _atexit(func,arg){}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-ExceptionInfoAttrs.SIZE;this.set_type=function(type){HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]=type};this.get_type=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]};this.set_destructor=function(destructor){HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]=destructor};this.get_destructor=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]};this.set_refcount=function(refcount){HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=refcount};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]!=0};this.init=function(type,destructor){this.set_type(type);this.set_destructor(destructor);this.set_refcount(0);this.set_caught(false);this.set_rethrown(false)};this.add_ref=function(){var value=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=value+1};this.release_ref=function(){var prev=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=prev-1;return prev===1}}function CatchInfo(ptr){this.free=function(){_free(this.ptr);this.ptr=0};this.set_base_ptr=function(basePtr){HEAP32[this.ptr>>2]=basePtr};this.get_base_ptr=function(){return HEAP32[this.ptr>>2]};this.set_adjusted_ptr=function(adjustedPtr){var ptrSize=4;HEAP32[this.ptr+ptrSize>>2]=adjustedPtr};this.get_adjusted_ptr=function(){var ptrSize=4;return HEAP32[this.ptr+ptrSize>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_exception_info().get_type());if(isPointer){return HEAP32[this.get_base_ptr()>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.get_base_ptr()};this.get_exception_info=function(){return new ExceptionInfo(this.get_base_ptr())};if(ptr===undefined){this.ptr=_malloc(8);this.set_adjusted_ptr(0)}else{this.ptr=ptr}}var exceptionCaught=[];function exception_addRef(info){info.add_ref()}var uncaughtExceptionCount=0;function ___cxa_begin_catch(ptr){var catchInfo=new CatchInfo(ptr);var info=catchInfo.get_exception_info();if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(catchInfo);exception_addRef(info);return catchInfo.get_exception_ptr()}function ___cxa_call_unexpected(exception){err("Unexpected exception thrown, this is not properly supported - aborting");ABORT=true;throw exception}function ___cxa_current_primary_exception(){if(!exceptionCaught.length){return 0}var catchInfo=exceptionCaught[exceptionCaught.length-1];exception_addRef(catchInfo.get_exception_info());return catchInfo.get_base_ptr()}function ___cxa_free_exception(ptr){try{return _free(new ExceptionInfo(ptr).ptr)}catch(e){}}function exception_decRef(info){if(info.release_ref()&&!info.get_rethrown()){var destructor=info.get_destructor();if(destructor){wasmTable.get(destructor)(info.excPtr)}___cxa_free_exception(info.excPtr)}}function ___cxa_decrement_exception_refcount(ptr){if(!ptr)return;exception_decRef(new ExceptionInfo(ptr))}var exceptionLast=0;function ___cxa_end_catch(){_setThrew(0);var catchInfo=exceptionCaught.pop();exception_decRef(catchInfo.get_exception_info());catchInfo.free();exceptionLast=0}function ___resumeException(catchInfoPtr){var catchInfo=new CatchInfo(catchInfoPtr);var ptr=catchInfo.get_base_ptr();if(!exceptionLast){exceptionLast=ptr}catchInfo.free();throw ptr}function ___cxa_find_matching_catch_2(){var thrown=exceptionLast;if(!thrown){setTempRet0(0|0);return 0|0}var info=new ExceptionInfo(thrown);var thrownType=info.get_type();var catchInfo=new CatchInfo;catchInfo.set_base_ptr(thrown);if(!thrownType){setTempRet0(0|0);return catchInfo.ptr|0}var typeArray=Array.prototype.slice.call(arguments);var stackTop=stackSave();var exceptionThrowBuf=stackAlloc(4);HEAP32[exceptionThrowBuf>>2]=thrown;for(var i=0;i>2];if(thrown!==adjusted){catchInfo.set_adjusted_ptr(adjusted)}setTempRet0(caughtType|0);return catchInfo.ptr|0}}stackRestore(stackTop);setTempRet0(thrownType|0);return catchInfo.ptr|0}function ___cxa_find_matching_catch_3(){var thrown=exceptionLast;if(!thrown){setTempRet0(0|0);return 0|0}var info=new ExceptionInfo(thrown);var thrownType=info.get_type();var catchInfo=new CatchInfo;catchInfo.set_base_ptr(thrown);if(!thrownType){setTempRet0(0|0);return catchInfo.ptr|0}var typeArray=Array.prototype.slice.call(arguments);var stackTop=stackSave();var exceptionThrowBuf=stackAlloc(4);HEAP32[exceptionThrowBuf>>2]=thrown;for(var i=0;i>2];if(thrown!==adjusted){catchInfo.set_adjusted_ptr(adjusted)}setTempRet0(caughtType|0);return catchInfo.ptr|0}}stackRestore(stackTop);setTempRet0(thrownType|0);return catchInfo.ptr|0}function ___cxa_find_matching_catch_4(){var thrown=exceptionLast;if(!thrown){setTempRet0(0|0);return 0|0}var info=new ExceptionInfo(thrown);var thrownType=info.get_type();var catchInfo=new CatchInfo;catchInfo.set_base_ptr(thrown);if(!thrownType){setTempRet0(0|0);return catchInfo.ptr|0}var typeArray=Array.prototype.slice.call(arguments);var stackTop=stackSave();var exceptionThrowBuf=stackAlloc(4);HEAP32[exceptionThrowBuf>>2]=thrown;for(var i=0;i>2];if(thrown!==adjusted){catchInfo.set_adjusted_ptr(adjusted)}setTempRet0(caughtType|0);return catchInfo.ptr|0}}stackRestore(stackTop);setTempRet0(thrownType|0);return catchInfo.ptr|0}function ___cxa_find_matching_catch_5(){var thrown=exceptionLast;if(!thrown){setTempRet0(0|0);return 0|0}var info=new ExceptionInfo(thrown);var thrownType=info.get_type();var catchInfo=new CatchInfo;catchInfo.set_base_ptr(thrown);if(!thrownType){setTempRet0(0|0);return catchInfo.ptr|0}var typeArray=Array.prototype.slice.call(arguments);var stackTop=stackSave();var exceptionThrowBuf=stackAlloc(4);HEAP32[exceptionThrowBuf>>2]=thrown;for(var i=0;i>2];if(thrown!==adjusted){catchInfo.set_adjusted_ptr(adjusted)}setTempRet0(caughtType|0);return catchInfo.ptr|0}}stackRestore(stackTop);setTempRet0(thrownType|0);return catchInfo.ptr|0}function ___cxa_find_matching_catch_8(){var thrown=exceptionLast;if(!thrown){setTempRet0(0|0);return 0|0}var info=new ExceptionInfo(thrown);var thrownType=info.get_type();var catchInfo=new CatchInfo;catchInfo.set_base_ptr(thrown);if(!thrownType){setTempRet0(0|0);return catchInfo.ptr|0}var typeArray=Array.prototype.slice.call(arguments);var stackTop=stackSave();var exceptionThrowBuf=stackAlloc(4);HEAP32[exceptionThrowBuf>>2]=thrown;for(var i=0;i>2];if(thrown!==adjusted){catchInfo.set_adjusted_ptr(adjusted)}setTempRet0(caughtType|0);return catchInfo.ptr|0}}stackRestore(stackTop);setTempRet0(thrownType|0);return catchInfo.ptr|0}function ___cxa_increment_exception_refcount(ptr){if(!ptr)return;exception_addRef(new ExceptionInfo(ptr))}function ___cxa_rethrow(){var catchInfo=exceptionCaught.pop();var info=catchInfo.get_exception_info();var ptr=catchInfo.get_base_ptr();if(!info.get_rethrown()){exceptionCaught.push(catchInfo);info.set_rethrown(true);info.set_caught(false);uncaughtExceptionCount++}else{catchInfo.free()}exceptionLast=ptr;throw ptr}function ___cxa_rethrow_primary_exception(ptr){if(!ptr)return;var catchInfo=new CatchInfo;catchInfo.set_base_ptr(ptr);var info=catchInfo.get_exception_info();exceptionCaught.push(catchInfo);info.set_rethrown(true);___cxa_rethrow()}function ___cxa_thread_atexit(a0,a1){return _atexit(a0,a1)}function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw ptr}function ___cxa_uncaught_exceptions(){return uncaughtExceptionCount}function _gmtime_r(time,tmPtr){var date=new Date(HEAP32[time>>2]*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();HEAP32[tmPtr+36>>2]=0;HEAP32[tmPtr+32>>2]=0;var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;if(!_gmtime_r.GMTString)_gmtime_r.GMTString=allocateUTF8("GMT");HEAP32[tmPtr+40>>2]=_gmtime_r.GMTString;return tmPtr}function ___gmtime_r(a0,a1){return _gmtime_r(a0,a1)}function _tzset(){if(_tzset.called)return;_tzset.called=true;var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAP32[__get_timezone()>>2]=stdTimezoneOffset*60;HEAP32[__get_daylight()>>2]=Number(winterOffset!=summerOffset);function extractZone(date){var match=date.toTimeString().match(/\(([A-Za-z ]+)\)$/);return match?match[1]:"GMT"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=allocateUTF8(winterName);var summerNamePtr=allocateUTF8(summerName);if(summerOffset>2]=winterNamePtr;HEAP32[__get_tzname()+4>>2]=summerNamePtr}else{HEAP32[__get_tzname()>>2]=summerNamePtr;HEAP32[__get_tzname()+4>>2]=winterNamePtr}}function _localtime_r(time,tmPtr){_tzset();var date=new Date(HEAP32[time>>2]*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var start=new Date(date.getFullYear(),0,1);var yday=(date.getTime()-start.getTime())/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst;var zonePtr=HEAP32[__get_tzname()+(dst?4:0)>>2];HEAP32[tmPtr+40>>2]=zonePtr;return tmPtr}function ___localtime_r(a0,a1){return _localtime_r(a0,a1)}var PATH={splitPath:function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};function getRandomDevice(){if(typeof crypto==="object"&&typeof crypto["getRandomValues"]==="function"){var randomBuffer=new Uint8Array(1);return function(){crypto.getRandomValues(randomBuffer);return randomBuffer[0]}}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");return function(){return crypto_module["randomBytes"](1)[0]}}catch(e){}}return function(){abort("randomDevice")}}var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:function(from,to){from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()},put_char:function(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};function mmapAlloc(size){var alignedSize=alignMemory(size,16384);var ptr=_malloc(alignedSize);while(size=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0);return},resizeFileStorage:function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0;return}if(!node.contents||node.contents.subarray){var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize;return}if(!node.contents)node.contents=[];if(node.contents.length>newSize)node.contents.length=newSize;else while(node.contents.length=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length=stream.node.size)return 0;var chunk=stream.node.contents.slice(position,position+length);var ab=WORKERFS.reader.readAsArrayBuffer(chunk);buffer.set(new Uint8Array(ab),offset);return chunk.size},write:function(stream,buffer,offset,length,position){throw new FS.ErrnoError(29)},llseek:function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.size}}if(position<0){throw new FS.ErrnoError(28)}return position}}};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:function(path,opts){path=PATH_FS.resolve(FS.cwd(),path);opts=opts||{};if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};for(var key in defaults){if(opts[key]===undefined){opts[key]=defaults[key]}}if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),false);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath:function(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?mount+"/"+path:mount+path}path=path?node.name+"/"+path:node.name;node=node.parent}},hashName:function(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode:function(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:function(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:function(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:function(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:function(node){FS.hashRemoveNode(node)},isRoot:function(node){return node===node.parent},isMountpoint:function(node){return!!node.mounted},isFile:function(mode){return(mode&61440)===32768},isDir:function(mode){return(mode&61440)===16384},isLink:function(mode){return(mode&61440)===40960},isChrdev:function(mode){return(mode&61440)===8192},isBlkdev:function(mode){return(mode&61440)===24576},isFIFO:function(mode){return(mode&61440)===4096},isSocket:function(mode){return(mode&49152)===49152},flagModes:{"r":0,"r+":2,"w":577,"w+":578,"a":1089,"a+":1090},modeStringToFlags:function(str){var flags=FS.flagModes[str];if(typeof flags==="undefined"){throw new Error("Unknown file open mode: "+str)}return flags},flagsToPermissionString:function(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions:function(node,perms){if(FS.ignorePermissions){return 0}if(perms.indexOf("r")!==-1&&!(node.mode&292)){return 2}else if(perms.indexOf("w")!==-1&&!(node.mode&146)){return 2}else if(perms.indexOf("x")!==-1&&!(node.mode&73)){return 2}return 0},mayLookup:function(dir){var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:function(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete:function(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen:function(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:function(fd_start,fd_end){fd_start=fd_start||0;fd_end=fd_end||FS.MAX_OPEN_FDS;for(var fd=fd_start;fd<=fd_end;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStream:function(fd){return FS.streams[fd]},createStream:function(stream,fd_start,fd_end){if(!FS.FSStream){FS.FSStream=function(){};FS.FSStream.prototype={object:{get:function(){return this.node},set:function(val){this.node=val}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}}}}var newStream=new FS.FSStream;for(var p in stream){newStream[p]=stream[p]}stream=newStream;var fd=FS.nextfd(fd_start,fd_end);stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:function(fd){FS.streams[fd]=null},chrdev_stream_ops:{open:function(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:function(){throw new FS.ErrnoError(70)}},major:function(dev){return dev>>8},minor:function(dev){return dev&255},makedev:function(ma,mi){return ma<<8|mi},registerDevice:function(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:function(dev){return FS.devices[dev]},getMounts:function(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:function(populate,callback){if(typeof populate==="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err("warning: "+FS.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work")}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(function(mount){if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount:function(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:function(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(function(hash){var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.indexOf(current.mount)!==-1){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:function(parent,name){return parent.node_ops.lookup(parent,name)},mknod:function(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create:function(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:function(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:function(path,mode){var dirs=path.split("/");var d="";for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=function(from,to){if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);if(typeof Uint8Array!="undefined")xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}else{return intArrayFromString(xhr.responseText||"",true)}};var lazyArray=this;lazyArray.setDataGetter(function(chunkNum){var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]==="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]==="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!=="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(function(key){var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}});stream_ops.read=function stream_ops_read(stream,buffer,offset,length,position){FS.forceLoadFile(node);var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i>2]=stat.dev;HEAP32[buf+4>>2]=0;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAP32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;HEAP32[buf+32>>2]=0;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAP32[buf+48>>2]=4096;HEAP32[buf+52>>2]=stat.blocks;HEAP32[buf+56>>2]=stat.atime.getTime()/1e3|0;HEAP32[buf+60>>2]=0;HEAP32[buf+64>>2]=stat.mtime.getTime()/1e3|0;HEAP32[buf+68>>2]=0;HEAP32[buf+72>>2]=stat.ctime.getTime()/1e3|0;HEAP32[buf+76>>2]=0;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+80>>2]=tempI64[0],HEAP32[buf+84>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},doMkdir:function(path,mode){path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0},doMknod:function(path,mode,dev){switch(mode&61440){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-28}FS.mknod(path,mode,dev);return 0},doReadlink:function(path,buf,bufsize){if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len},doAccess:function(path,amode){if(amode&~7){return-28}var node;var lookup=FS.lookupPath(path,{follow:true});node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0},doDup:function(path,flags,suggestFD){var suggest=FS.getStream(suggestFD);if(suggest)FS.close(suggest);return FS.open(path,flags,0,suggestFD,suggestFD).fd},doReadv:function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr}return ret},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);return stream},get64:function(low,high){return low}};function ___sys_dup2(oldfd,suggestFD){try{var old=SYSCALLS.getStreamFromFD(oldfd);if(old.fd===suggestFD)return suggestFD;return SYSCALLS.doDup(old.path,old.flags,suggestFD)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_dup3(fd,suggestFD,flags){try{var old=SYSCALLS.getStreamFromFD(fd);if(old.fd===suggestFD)return-28;return SYSCALLS.doDup(old.path,old.flags,suggestFD)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}var newStream;newStream=FS.open(stream.path,stream.flags,0,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 12:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 13:case 14:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_getcwd(buf,size){try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd);if(size>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;return 0}case 21524:{if(!stream.tty)return-59;return 0}default:abort("bad ioctl syscall "+op)}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_open(path,flags,varargs){SYSCALLS.varargs=varargs;try{var pathname=SYSCALLS.getStr(path);var mode=SYSCALLS.get();var stream=FS.open(pathname,flags,mode);return stream.fd}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_readlink(path,buf,bufsize){try{path=SYSCALLS.getStr(path);return SYSCALLS.doReadlink(path,buf,bufsize)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_rename(old_path,new_path){try{old_path=SYSCALLS.getStr(old_path);new_path=SYSCALLS.getStr(new_path);FS.rename(old_path,new_path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_unlink(path){try{path=SYSCALLS.getStr(path);FS.unlink(path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _abort(){abort()}function _clock(){if(_clock.start===undefined)_clock.start=Date.now();return(Date.now()-_clock.start)*(1e6/1e3)|0}function _difftime(time1,time0){return time1-time0}function _longjmp(env,value){_setThrew(env,value||1);throw"longjmp"}function _emscripten_longjmp(a0,a1){return _longjmp(a0,a1)}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;abortOnCannotGrowMemory(requestedSize)}var ENV={};function getExecutableName(){return thisProgram||"./this.program"}function getEnvStrings(){if(!getEnvStrings.strings){var lang=(typeof navigator==="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":lang,"_":getExecutableName()};for(var x in ENV){env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(x+"="+env[x])}getEnvStrings.strings=strings}return getEnvStrings.strings}function _environ_get(__environ,environ_buf){try{var bufSize=0;getEnvStrings().forEach(function(string,i){var ptr=environ_buf+bufSize;HEAP32[__environ+i*4>>2]=ptr;writeAsciiToMemory(string,ptr);bufSize+=string.length+1});return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _environ_sizes_get(penviron_count,penviron_buf_size){try{var strings=getEnvStrings();HEAP32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(function(string){bufSize+=string.length+1});HEAP32[penviron_buf_size>>2]=bufSize;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _exit(status){exit(status)}function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4;HEAP8[pbuf>>0]=type;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=SYSCALLS.doReadv(stream,iov,iovcnt);HEAP32[pnum>>2]=num;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){try{var stream=SYSCALLS.getStreamFromFD(fd);var HIGH_OFFSET=4294967296;var offset=offset_high*HIGH_OFFSET+(offset_low>>>0);var DOUBLE_LIMIT=9007199254740992;if(offset<=-DOUBLE_LIMIT||offset>=DOUBLE_LIMIT){return-61}FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=SYSCALLS.doWritev(stream,iov,iovcnt);HEAP32[pnum>>2]=num;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _getTempRet0(){return getTempRet0()|0}function _llvm_eh_typeid_for(type){return type}function _mktime(tmPtr){_tzset();var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=(date.getTime()-start.getTime())/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();return date.getTime()/1e3|0}function _setTempRet0($i){setTempRet0($i|0)}function __isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}function __arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum}var __MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var __MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function __addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=__isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value==="number"?value.toString():value||"";while(str.length0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}else{return thisDate.getFullYear()}}else{return thisDate.getFullYear()-1}}var EXPANSION_RULES_2={"%a":function(date){return WEEKDAYS[date.tm_wday].substring(0,3)},"%A":function(date){return WEEKDAYS[date.tm_wday]},"%b":function(date){return MONTHS[date.tm_mon].substring(0,3)},"%B":function(date){return MONTHS[date.tm_mon]},"%C":function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":function(date){return leadingNulls(date.tm_mday,2)},"%e":function(date){return leadingSomething(date.tm_mday,2," ")},"%g":function(date){return getWeekBasedYear(date).toString().substring(2)},"%G":function(date){return getWeekBasedYear(date)},"%H":function(date){return leadingNulls(date.tm_hour,2)},"%I":function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":function(date){return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900)?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,date.tm_mon-1),3)},"%m":function(date){return leadingNulls(date.tm_mon+1,2)},"%M":function(date){return leadingNulls(date.tm_min,2)},"%n":function(){return"\n"},"%p":function(date){if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}else{return"PM"}},"%S":function(date){return leadingNulls(date.tm_sec,2)},"%t":function(){return"\t"},"%u":function(date){return date.tm_wday||7},"%U":function(date){var janFirst=new Date(date.tm_year+1900,0,1);var firstSunday=janFirst.getDay()===0?janFirst:__addDays(janFirst,7-janFirst.getDay());var endDate=new Date(date.tm_year+1900,date.tm_mon,date.tm_mday);if(compareByDay(firstSunday,endDate)<0){var februaryFirstUntilEndMonth=__arraySum(__isLeapYear(endDate.getFullYear())?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,endDate.getMonth()-1)-31;var firstSundayUntilEndJanuary=31-firstSunday.getDate();var days=firstSundayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();return leadingNulls(Math.ceil(days/7),2)}return compareByDay(firstSunday,janFirst)===0?"01":"00"},"%V":function(date){var janFourthThisYear=new Date(date.tm_year+1900,0,4);var janFourthNextYear=new Date(date.tm_year+1901,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);var endDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);if(compareByDay(endDate,firstWeekStartThisYear)<0){return"53"}if(compareByDay(firstWeekStartNextYear,endDate)<=0){return"01"}var daysDifference;if(firstWeekStartThisYear.getFullYear()=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":function(date){return date.tm_zone},"%%":function(){return"%"}};for(var rule in EXPANSION_RULES_2){if(pattern.indexOf(rule)>=0){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function _strftime_l(s,maxsize,format,tm){return _strftime(s,maxsize,format,tm)}function _system(command){if(ENVIRONMENT_IS_NODE){if(!command)return 1;var cmdstr=UTF8ToString(command);if(!cmdstr.length)return 0;var cp=require("child_process");var ret=cp.spawnSync(cmdstr,[],{shell:true,stdio:"inherit"});var _W_EXITCODE=function(ret,sig){return ret<<8|sig};if(ret.status===null){var signalToNumber=function(sig){switch(sig){case"SIGHUP":return 1;case"SIGINT":return 2;case"SIGQUIT":return 3;case"SIGFPE":return 8;case"SIGKILL":return 9;case"SIGALRM":return 14;case"SIGTERM":return 15}return 2};return _W_EXITCODE(0,signalToNumber(ret.signal))}return _W_EXITCODE(ret.status,0)}if(!command)return 0;setErrNo(6);return-1}function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.staticInit();Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;Module["FS_unlink"]=FS.unlink;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}__ATINIT__.push({func:function(){___wasm_call_ctors()}});var asmLibraryArg={"ya":___clock_gettime,"m":___cxa_allocate_exception,"q":___cxa_begin_catch,"$":___cxa_call_unexpected,"ka":___cxa_current_primary_exception,"T":___cxa_decrement_exception_refcount,"x":___cxa_end_catch,"b":___cxa_find_matching_catch_2,"i":___cxa_find_matching_catch_3,"G":___cxa_find_matching_catch_4,"B":___cxa_find_matching_catch_5,"Ca":___cxa_find_matching_catch_8,"n":___cxa_free_exception,"S":___cxa_increment_exception_refcount,"_":___cxa_rethrow,"ja":___cxa_rethrow_primary_exception,"N":___cxa_thread_atexit,"u":___cxa_throw,"la":___cxa_uncaught_exceptions,"qa":___gmtime_r,"pa":___localtime_r,"e":___resumeException,"sa":___sys_dup2,"ta":___sys_dup3,"O":___sys_fcntl64,"Ba":___sys_fstat64,"za":___sys_getcwd,"va":___sys_ioctl,"xa":___sys_lstat64,"P":___sys_open,"Aa":___sys_readlink,"ra":___sys_rename,"wa":___sys_rmdir,"W":___sys_stat64,"V":___sys_unlink,"Y":_abort,"Z":_clock,"Fa":_difftime,"X":_emscripten_longjmp,"ga":_emscripten_memcpy_big,"ha":_emscripten_resize_heap,"na":_environ_get,"oa":_environ_sizes_get,"w":_exit,"I":_fd_close,"ma":_fd_fdstat_get,"ua":_fd_read,"ba":_fd_seek,"U":_fd_write,"a":_getTempRet0,"Q":invoke_diii,"R":invoke_fiii,"v":invoke_i,"d":invoke_ii,"c":invoke_iii,"f":invoke_iiii,"r":invoke_iiiii,"s":invoke_iiiiii,"A":invoke_iiiiiii,"D":invoke_iiiiiiii,"H":invoke_iiiiiiiii,"L":invoke_iiiiiiiiiiii,"Ha":invoke_iiiiiiiiiiiii,"fa":invoke_iiij,"da":invoke_jiii,"aa":invoke_jiiii,"k":invoke_v,"j":invoke_vi,"g":invoke_vii,"h":invoke_viii,"l":invoke_viiii,"o":invoke_viiiii,"p":invoke_viiiiii,"C":invoke_viiiiiii,"E":invoke_viiiiiiii,"F":invoke_viiiiiiiii,"z":invoke_viiiiiiiiii,"y":invoke_viiiiiiiiiii,"K":invoke_viiiiiiiiiiiiiii,"ca":invoke_viij,"ea":invoke_vij,"t":_llvm_eh_typeid_for,"Da":_mktime,"J":_setTempRet0,"Ga":_strftime,"ia":_strftime_l,"Ea":_system,"M":_time};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["Ka"]).apply(null,arguments)};var _main=Module["_main"]=function(){return(_main=Module["_main"]=Module["asm"]["La"]).apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){return(___errno_location=Module["___errno_location"]=Module["asm"]["Ma"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["Na"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["Oa"]).apply(null,arguments)};var __get_tzname=Module["__get_tzname"]=function(){return(__get_tzname=Module["__get_tzname"]=Module["asm"]["Pa"]).apply(null,arguments)};var __get_daylight=Module["__get_daylight"]=function(){return(__get_daylight=Module["__get_daylight"]=Module["asm"]["Qa"]).apply(null,arguments)};var __get_timezone=Module["__get_timezone"]=function(){return(__get_timezone=Module["__get_timezone"]=Module["asm"]["Ra"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return(stackSave=Module["stackSave"]=Module["asm"]["Sa"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return(stackRestore=Module["stackRestore"]=Module["asm"]["Ta"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return(stackAlloc=Module["stackAlloc"]=Module["asm"]["Ua"]).apply(null,arguments)};var _setThrew=Module["_setThrew"]=function(){return(_setThrew=Module["_setThrew"]=Module["asm"]["Va"]).apply(null,arguments)};var ___cxa_can_catch=Module["___cxa_can_catch"]=function(){return(___cxa_can_catch=Module["___cxa_can_catch"]=Module["asm"]["Wa"]).apply(null,arguments)};var ___cxa_is_pointer_type=Module["___cxa_is_pointer_type"]=function(){return(___cxa_is_pointer_type=Module["___cxa_is_pointer_type"]=Module["asm"]["Xa"]).apply(null,arguments)};var dynCall_iiij=Module["dynCall_iiij"]=function(){return(dynCall_iiij=Module["dynCall_iiij"]=Module["asm"]["Ya"]).apply(null,arguments)};var dynCall_jiii=Module["dynCall_jiii"]=function(){return(dynCall_jiii=Module["dynCall_jiii"]=Module["asm"]["Za"]).apply(null,arguments)};var dynCall_viij=Module["dynCall_viij"]=function(){return(dynCall_viij=Module["dynCall_viij"]=Module["asm"]["_a"]).apply(null,arguments)};var dynCall_vij=Module["dynCall_vij"]=function(){return(dynCall_vij=Module["dynCall_vij"]=Module["asm"]["$a"]).apply(null,arguments)};var dynCall_jiiii=Module["dynCall_jiiii"]=function(){return(dynCall_jiiii=Module["dynCall_jiiii"]=Module["asm"]["ab"]).apply(null,arguments)};function invoke_ii(index,a1){var sp=stackSave();try{return wasmTable.get(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{wasmTable.get(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return wasmTable.get(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{wasmTable.get(index)()}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{wasmTable.get(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return wasmTable.get(index)()}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_fiii(index,a1,a2,a3){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiij(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_iiij(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_vij(index,a1,a2,a3){var sp=stackSave();try{dynCall_vij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_jiii(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jiii(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viij(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_viij(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_jiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jiiii(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}Module["addRunDependency"]=addRunDependency;Module["removeRunDependency"]=removeRunDependency;Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;Module["FS_unlink"]=FS.unlink;Module["callMain"]=callMain;Module["FS"]=FS;var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}var calledMain=false;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function callMain(args){var entryFunction=Module["_main"];args=args||[];var argc=args.length+1;var argv=stackAlloc((argc+1)*4);HEAP32[argv>>2]=allocateUTF8OnStack(thisProgram);for(var i=1;i>2)+i]=allocateUTF8OnStack(args[i-1])}HEAP32[(argv>>2)+argc]=0;try{var ret=entryFunction(argc,argv);exit(ret,true)}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack]}err("exception thrown: "+toLog);quit_(1,e)}}finally{calledMain=true}}function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain(args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime){}else{EXITSTATUS=status;exitRuntime();if(Module["onExit"])Module["onExit"](status);ABORT=true}quit_(status,new ExitStatus(status))}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run(); + + + return silice;//.ready +} +); +})(); +if (typeof exports === 'object' && typeof module === 'object') + module.exports = silice; +else if (typeof define === 'function' && define['amd']) + define([], function() { return silice; }); +else if (typeof exports === 'object') + exports["silice"] = silice; diff --git a/src/worker/wasm/silice.wasm b/src/worker/wasm/silice.wasm new file mode 100755 index 00000000..97d4e725 Binary files /dev/null and b/src/worker/wasm/silice.wasm differ diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts index b1a3608a..a34ebe0b 100644 --- a/src/worker/workermain.ts +++ b/src/worker/workermain.ts @@ -209,6 +209,7 @@ var PLATFORM_PARAMS = { libargs: ['atari5200.lib', '-D', '__CARTFLAGS__=255'], }, 'verilog': { + extra_compile_files: ['8bitworkshop.v'], }, 'astrocade': { code_start: 0x2000, @@ -271,7 +272,7 @@ var PLATFORM_PARAMS = { cfgfile: 'devel-6502.cfg', libargs: ['crt0.o', 'sim6502.lib'], extra_link_files: ['crt0.o', 'devel-6502.cfg'], - }, + }, }; PLATFORM_PARAMS['sms-sms-libcv'] = PLATFORM_PARAMS['sms-sg1000-libcv']; @@ -770,6 +771,7 @@ function assembleDASM(step:BuildStep) { var errors = []; var errorMatcher = msvcErrorMatcher(errors); function match_fn(s) { + // TODO: what if s is not string? (startsWith is not a function) var matches = re_usl.exec(s); if (matches) { var key = matches[1]; @@ -2670,6 +2672,62 @@ function compileBASIC(step:BuildStep) { } } +function compileSilice(step:BuildStep) { + // TODO: fastbasic-fp? + loadNative("silice"); + var params = step.params; + gatherFiles(step, {mainFilePath:"main.ice"}); + var destpath = step.prefix + '.v'; + var errors : WorkerError[] = []; + var errfile : string; + var errline : number; + if (staleFiles(step, [destpath])) { + var match_fn = (s: string) => { + s = (s as any).replaceAll(/\033\[\d+\w/g, ''); + var mf = /file:\s*(\w+)/.exec(s); + var ml = /line:\s+(\d+)/.exec(s); + if (mf) errfile = mf[1]; + else if (ml) errline = parseInt(ml[1]); + else if (errfile && errline && s.length > 1) { + if (s.length > 2) { + errors.push({path:errfile+".ice", line:errline, msg:s}); + } else { + errfile = null; + errline = null; + } + } + } + var silice = emglobal.silice({ + instantiateWasm: moduleInstFn('silice'), + noInitialRun:true, + print:match_fn, + printErr:match_fn, + }); + var FS = silice['FS']; + setupFS(FS, 'Silice'); + populateFiles(step, FS); + populateExtraFiles(step, FS, params.extra_compile_files); + const FWDIR = '/share/frameworks'; + var args = [ + '-D', 'NTSC=1', + '--frameworks_dir', FWDIR, + '-f', `/8bitworkshop.v`, + '-o', destpath, + step.path]; + execMain(step, silice, args); + if (errors.length) + return {errors:errors}; + var vout = FS.readFile(destpath, {encoding:'utf8'}); + putWorkFile(destpath, vout); + } + return { + nexttool:"verilator", + path:destpath, + args:[destpath], + files:[destpath], + }; +} + //////////////////////////// var TOOLS = { @@ -2703,6 +2761,7 @@ var TOOLS = { 'merlin32': assembleMerlin32, 'fastbasic': compileFastBasic, 'basic': compileBASIC, + 'silice': compileSilice, } var TOOL_PRELOADFS = { @@ -2726,6 +2785,7 @@ var TOOL_PRELOADFS = { 'bataribasic': '2600basic', 'inform6': 'inform', 'fastbasic': '65-atari8', + 'silice': 'Silice', } function applyDefaultErrorPath(errors:WorkerError[], path:string) {