Merge pull request #109 from daveshah1/up5k

Support for new UltraPlus features
This commit is contained in:
Clifford Wolf 2017-11-21 18:19:47 +01:00 committed by GitHub
commit 6e9a2da5c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 24907 additions and 119 deletions

View File

@ -100,6 +100,11 @@ Here is a list of currently supported parts and the corresponding options for ar
<tr><td>iCE40-HX8K-CT256</td><td>256-ball caBGA (14 x 14 mm)</td><td>0.80 mm</td><td>206</td><td>-d 8k -P ct256</td><td>-d hx8k</td></tr>
</table>
<p>
Experimental support is also included for one iCE40 UltraPlus device, the iCE40-UP5K-SG48, including support for some of
the new UltraPlus features such as DSPs, SPRAM and internal oscillators.
</p>
<p>
Current work focuses on further improving our timing analysis flow.
</p>
@ -309,6 +314,8 @@ The FPGA fabric is divided into tiles. There are IO, RAM and LOGIC tiles.
<li><a href="format.html">The Bitstream File Format</a></li>
<li><a href="bitdocs-1k/">The iCE40 HX1K Bit Docs</a></li>
<li><a href="bitdocs-8k/">The iCE40 HX8K Bit Docs</a></li>
<li><a href="ultraplus.html">Notes on UltraPlus features</a></li>
</ul>
<p>

267
docs/ultraplus.html Normal file
View File

@ -0,0 +1,267 @@
<!DOCTYPE html>
<html><head><meta charset="UTF-8">
<style>
.ctab {
margin-left: auto;
margin-right: auto;
border: 1px solid gray;
}
.ctab td, .ctab th {
padding: 3px;
border: 1px solid gray;
}
.ctab td {
font-family:monospace;
}
</style>
<title>Project IceStorm &ndash; UltraPlus Features Documentation</title>
</head><body>
<h1>Project IceStorm &ndash; UltraPlus Features Documentation</h1>
<p>
<i><a href=".">Project IceStorm</a> aims at documenting the bitstream format of Lattice iCE40
FPGAs and providing simple tools for analyzing and creating bitstream files.
This is work in progress.</i>
</p>
<p>The ice40 UltraPlus devices have a number of new features compared to the older LP/HX series
devices, in particular:
<ul>
<li>Internal DSP units, capable of 16-bit multiply and 32-bit accumulate.</li>
<li>1Mbit of extra single-ported RAM, in addition to the usual BRAM</li>
<li>Internal hard IP cores for I2C and SPI</li>
<li>2 internal oscillators, 48MHz (with divider) and 10kHz</li>
<li>24mA constant current LED ouputs and PWM hard IP</li>
</ul>
In order to implement these new features, a significant architecural change has been made: the
left and right sides of the device are no longer IO, but instead DSP and IPConnect tiles.
</p>
<p>Currently icestorm and arachne-pnr support the DSPs (except for cascading), SPRAM , internal oscillators and constant current
LED drivers. Work to support the remaining features is underway.</p>
<h2>DSP Tiles</h2>
<p>Each MAC16 DSP comprises of 4 DSP tiles, all of which perform part of the DSP function and have
different routing bit configurations. Structually they are similar to logic tiles, but with the DSP
function wired into where the LUTs and DFFs would be. The four types of DSP tiles will be referred to
as DSP0 through DSP3, with DSP0 at the lowest y-position. One signal CO, is also routed through the
IPConnect tile above the DSP tile, referred to as IPCON4 in this context.
The location of signals and configuration bits is documented below.</p>
<p>
<strong>Signal Assignments</strong><br/>
<table class="ctab">
<tr><th>SB_MAC16 port</th><th>DSP0</th><th>DSP1</th><th>DSP2</th><th>DSP3</th><th>IPCON4</th></tr>
<tr><td>CLK</td><td>-</td><td>-</td><td>lutff_global/clk</td><td>-</td><td>-</td></tr>
<tr><td>CE</td><td>-</td><td>-</td><td>lutff_global/cen</td><td>-</td><td>-</td></tr>
<tr><td>C[7:0]</td><td>-</td><td>-</td><td>-</td><td>lutff_[7:0]/in_3</td><td>-</td></tr>
<tr><td>C[15:8]</td><td>-</td><td>-</td><td>-</td><td>lutff_[7:0]/in_1</td><td>-</td></tr>
<tr><td>A[7:0]</td><td>-</td><td>-</td><td>lutff_[7:0]/in_3</td><td>-</td><td>-</td></tr>
<tr><td>A[15:8]</td><td>-</td><td>-</td><td>lutff_[7:0]/in_1</td><td>-</td><td>-</td></tr>
<tr><td>B[7:0]</td><td>-</td><td>lutff_[7:0]/in_3</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>B[15:8]</td><td>-</td><td>lutff_[7:0]/in_1</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>D[7:0]</td><td>lutff_[7:0]/in_3</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>D[15:8]</td><td>lutff_[7:0]/in_1</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>IRSTTOP</td><td>-</td><td>lutff_global/s_r</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>IRSTBOT</td><td>lutff_global/s_r</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>ORSTTOP</td><td>-</td><td>-</td><td>-</td><td>lutff_global/s_r</td><td>-</td></tr>
<tr><td>ORSTBOT</td><td>-</td><td>-</td><td>lutff_global/s_r</td><td>-</td><td>-</td></tr>
<tr><td>AHOLD</td><td>-</td><td>-</td><td>lutff_0/in_0</td><td>-</td><td>-</td></tr>
<tr><td>BHOLD</td><td>-</td><td>lutff_0/in_0</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>CHOLD</td><td>-</td><td>-</td><td>-</td><td>lutff_0/in_0</td><td>-</td></tr>
<tr><td>DHOLD</td><td>lutff_0/in_0</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>OHOLDTOP</td><td>-</td><td>-</td><td>-</td><td>lutff_1/in_0</td><td>-</td></tr>
<tr><td>OHOLDBOT</td><td>lutff_1/in_0</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>ADDSUBTOP</td><td>-</td><td>-</td><td>-</td><td>lutff_3/in_0</td><td>-</td></tr>
<tr><td>ADDSUBBOT</td><td>lutff_3/in_0</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>OLOADTOP</td><td>-</td><td>-</td><td>-</td><td>lutff_2/in_0</td><td>-</td></tr>
<tr><td>OLOADBOT</td><td>lutff_2/in_0</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>CI</td><td>lutff_4/in_0</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>O[31:0]</td><td>mult/O_[7:0]</td><td>mult/O_[15:8]</td><td>mult/O_[23:16]</td><td>mult/O_[31:24]</td><td>-</td></tr>
<tr><td>CO</td><td>-</td><td>-</td><td>-</td><td>-</td><td>slf_op_0</td></tr>
</table>
</p>
<p>
<strong>Configuration Bits</strong><br/>
<p>The DSP configuration bits mostly follow the order stated in the ICE Technology Library document, where they are described as <span style="font-family:monospace">CBIT[24:0]</span>. For most DSP tiles,
these follow a logical order where <span style="font-family:monospace">CBIT[7:0]</span> maps to DSP0 <span style="font-family:monospace">CBIT[7:0]</span>; <span style="font-family:monospace">CBIT[15:8]</span>
to DSP1 <span style="font-family:monospace">CBIT[7:0]</span>, <span style="font-family:monospace">CBIT[23:16]</span> to DSP2 <span style="font-family:monospace">CBIT[7:0]</span>
and <span style="font-family:monospace">CBIT[24]</span> to DSP3 <span style="font-family:monospace">CBIT0</span>.
</p>
<p>However, there is one location where configuration bits are swapped between DSP tiles and IPConnect tiles. In DSP1 (0, 16) <span style="font-family:monospace">CBIT[4:1]</span> are used
for IP such as the internal oscillator, and the DSP configuration bits are then located in IPConnect tile (0, 19) <span style="font-family:monospace">CBIT[6:3]</span>.</p>
<p>The full list of configuration bits, including the changes for the DSP at (0, 15) are described in the table below.</p>
<table class="ctab">
<tr><th>Parameter</th><th>Normal Position</th><th>DSP (0, 15)<br/>Changes</th></tr>
<tr><td>C_REG</td><td>DSP0.CBIT_0</td><td></td></tr>
<tr><td>A_REG</td><td>DSP0.CBIT_1</td><td></td></tr>
<tr><td>B_REG</td><td>DSP0.CBIT_2</td><td></td></tr>
<tr><td>D_REG</td><td>DSP0.CBIT_3</td><td></td></tr>
<tr><td>TOP_8x8_MULT_REG</td><td>DSP0.CBIT_4</td><td></td></tr>
<tr><td>BOT_8x8_MULT_REG</td><td>DSP0.CBIT_5</td><td></td></tr>
<tr><td>PIPELINE_16x16_MULT_REG1</td><td>DSP0.CBIT_6</td><td></td></tr>
<tr><td>PIPELINE_16x16_MULT_REG2</td><td>DSP0.CBIT_7</td><td></td></tr>
<tr><td>TOPOUTPUT_SELECT[0]</td><td>DSP1.CBIT_0</td><td></td></tr>
<tr><td>TOPOUTPUT_SELECT[1]</td><td>DSP1.CBIT_1</td><td>(0, 19).CBIT_3</td></tr>
<tr><td>TOPADDSUB_LOWERINPUT[1:0]</td><td>DSP1.CBIT_[3:2]</td><td>(0, 19).CBIT_[5:4]</td></tr>
<tr><td>TOPADDSUB_UPPERINUT</td><td>DSP1.CBIT_4</td><td>(0, 19).CBIT_6</td></tr>
<tr><td>TOPADDSUB_CARRYSELECT[1:0]</td><td>DSP1.CBIT_[6:5]</td><td></td></tr>
<tr><td>BOTOUTPUT_SELECT[0]</td><td>DSP1.CBIT_7</td><td></td></tr>
<tr><td>BOTOUTPUT_SELECT[1]</td><td>DSP2.CBIT_0</td><td></td></tr>
<tr><td>BOTADDSUB_LOWERINPUT[1:0]</td><td>DSP2.CBIT_[2:1]</td><td></td></tr>
<tr><td>BOTADDSUB_UPPERINPUT</td><td>DSP2.CBIT_3</td><td></td></tr>
<tr><td>BOTADDSUB_CARRYSELECT[1:0]</td><td>DSP2.CBIT_[5:4]</td><td></td></tr>
<tr><td>MODE_8x8</td><td>DSP2.CBIT_6</td><td></td></tr>
<tr><td>A_SIGNED</td><td>DSP2.CBIT_7</td><td></td></tr>
<tr><td>B_SIGNED</td><td>DSP3.CBIT_0</td><td></td></tr>
</table>
<p>Lattice document a limited number of supported configurations in the ICE Technology Library document, and Lattice's EDIF parser will
reject designs not following a supported configuration. It is not yet known whether unsupported configurations (such as mixed
signed and unsigned) function correctly or not.
<p>
<strong>Other Implementation Notes</strong><br/>
<p>
All active DSP tiles, and all IPConnect tiles whether used or not, have some bits set which reflect their logic tile heritage. The <span style="font-family:monospace">LC_<em>x</em></span>
bits which would be used to configure the logic cell, are set to the below pattern for each "logic cell" (interpreting them like a logic tile):<br/>
<br><span style="font-family:monospace">0000111100001111 0000</span><br/><br/>
Coincidentally or not, this corresponds to a buffer passing through input 2 to the output. For each "cell" the cascade bit <span style="font-family:monospace">LC0<em>x</em>_inmux02_5</span> is
also set, effectively creating one large chain, as this connects input 2 to the output of the previous LUT. The DSPs at least will not function unless these bits are set correctly, so they <!DOCTYPE html>
have some purpose and presumably indicate that the remains of a LUT are still present. There does not seem to be any case under which iCEcube generates a pattern other than this though.
</p>
</p>
<h2>IPConnect Tiles</h2>
<p>IPConnect tiles are used for connections to all of the other UltraPlus features, such as I2C/SPI, SPRAM, RGB and oscillators. Like DSP tiles,
they are structually similar to logic tiles. The outputs of IP functions are connected to nets named <span style="font-family:monospace">slf_op_0</span> through <span style="font-family:monospace">slf_op_7</span>,
and the inputs use the LUT/FF inputs in the same way as DSP tiles.</p>
<h2>Internal Oscillators</h2>
Both of the internal oscillators are connected through IPConnect tiles, with their outputs optionally connected to the global networks,
by setting the "padin" extra bit (the used global networks 4 and 5 don't have physical pins on UltraPlus devices).
<h3>SB_HFOSC</h3>
<p>The <span style="font-family:monospace">CLKHFPU</span> input connects through IPConnect tile (0, 29) input <span style="font-family:monospace">lutff_0/in_1</span>;
and the <span style="font-family:monospace">CLKHFEN</span> input connects through input <span style="font-family:monospace">lutff_7/in_3</span> of the same tile.<br/>
The <span style="font-family:monospace">CLKHF</span> output of SB_HFOSC is connected to both IPConnect tile (0, 28) output <span style="font-family:monospace">slf_op_7</span> and to the <span style="font-family:monospace">padin</span>
of <span style="font-family:monospace">glb_netwk_4</span>.</p>
<p>Configuration bit <span style="font-family:monospace">CLKHF_DIV[1]</span> maps to DSP1 tile (0, 16) config bit <span style="font-family:monospace">CBIT_4</span>, and
<span style="font-family:monospace">CLKHF_DIV[0]</span> maps to DSP1 tile (0, 16) config bit <span style="font-family:monospace">CBIT_3</span>.</p>
<h3>SB_LFOSC</h3>
<p>The <span style="font-family:monospace">CLKLFPU</span> input connects through IPConnect tile (25, 29) input <span style="font-family:monospace">lutff_0/in_1</span>;
and the <span style="font-family:monospace">CLKLFEN</span> input connects through input <span style="font-family:monospace">lutff_7/in_3</span> of the same tile.<br/>
The <span style="font-family:monospace">CLKLF</span> output of SB_LFOSC is connected to both IPConnect tile (25, 29) output <span style="font-family:monospace">slf_op_0</span> and to the <span style="font-family:monospace">padin</span>
of <span style="font-family:monospace">glb_netwk_5</span>.</p>
<p>SB_LFOSC has no configuration bits.</p>
<h2>SPRAM</h2>
<p>The UltraPlus devices have 1Mbit of extra single-ported RAM, split into 4 256kbit blocks. The full list of connections for each SPRAM block in the 5k device is shown below,
as well as the location of the 1 configuration bit which is set to enable use of that SPRAM block.</p>
<table class="ctab">
<tr><th>Signal</th><th>SPRAM (0, 0, 1)</th><th>SPRAM (0, 0, 2)</th><th>SPRAM (25, 0, 3)</th><th>SPRAM (25, 0, 4)</th></tr>
<tr><td>ADDRESS[1:0]</td><td>(0, 2, lutff_[1:0]/in_1)</td><td>(0, 2, lutff_[7:6]/in_0)</td><td>(25, 2, lutff_[1:0]/in_1)</td><td>(25, 2, lutff_[7:6]/in_0)</td></tr>
<tr><td>ADDRESS[7:2]</td><td>(0, 2, lutff_[7:2]/in_1)</td><td>(0, 3, lutff_[5:0]/in_3)</td><td>(25, 2, lutff_[7:2]/in_1)</td><td>(25, 3, lutff_[5:0]/in_3)</td></tr>
<tr><td>ADDRESS[9:8]</td><td>(0, 2, lutff_[1:0]/in_0)</td><td>(0, 3, lutff_[7:6]/in_3)</td><td>(25, 2, lutff_[1:0]/in_0)</td><td>(25, 3, lutff_[7:6]/in_3)</td></tr>
<tr><td>ADDRESS[13:10]</td><td>(0, 2, lutff_[5:2]/in_0)</td><td>(0, 3, lutff_[3:0]/in_1)</td><td>(25, 2, lutff_[5:2]/in_0)</td><td>(25, 3, lutff_[3:0]/in_1)</td></tr>
<tr><td>DATAIN[7:0]</td><td>(0, 1, lutff_[7:0]/in_3)</td><td>(0, 1, lutff_[7:0]/in_0)</td><td>(25, 1, lutff_[7:0]/in_3)</td><td>(25, 1, lutff_[7:0]/in_0)</td></tr>
<tr><td>DATAIN[15:8]</td><td>(0, 1, lutff_[7:0]/in_1)</td><td>(0, 2, lutff_[7:0]/in_3)</td><td>(25, 1, lutff_[7:0]/in_1)</td><td>(25, 2, lutff_[7:0]/in_3)</td></tr>
<tr><td>MASKWREN[3:0]</td><td>(0, 3, lutff_[3:0]/in_0)</td><td>(0, 3, lutff_[7:4]/in_0)</td><td>(25, 3, lutff_[3:0]/in_0)</td><td>(25, 3, lutff_[7:4]/in_0)</td></tr>
<tr><td>WREN</td><td>(0, 3, lutff_4/in_1)</td><td>(0, 3, lutff_5/in_1)</td><td>(25, 3, lutff_4/in_1)</td><td>(25, 3, lutff_5/in_1)</td></tr>
<tr><td>CHIPSELECT</td><td>(0, 3, lutff_6/in_1)</td><td>(0, 3, lutff_7/in_1)</td><td>(25, 3, lutff_6/in_1)</td><td>(25, 3, lutff_7/in_1)</td></tr>
<tr><td>CLOCK</td><td>(0, 1, clk)</td><td>(0, 2, clk)</td><td>(25, 1, clk)</td><td>(25, 2, clk)</td></tr>
<tr><td>STANDBY</td><td>(0, 4, lutff_0/in_3)</td><td>(0, 4, lutff_1/in_3)</td><td>(25, 4, lutff_0/in_3)</td><td>(25, 4, lutff_1/in_3)</td></tr>
<tr><td>SLEEP</td><td>(0, 4, lutff_2/in_3)</td><td>(0, 4, lutff_3/in_3)</td><td>(25, 4, lutff_2/in_3)</td><td>(25, 4, lutff_3/in_3)</td></tr>
<tr><td>POWEROFF</td><td>(0, 4, lutff_4/in_3)</td><td>(0, 4, lutff_5/in_3)</td><td>(25, 4, lutff_4/in_3)</td><td>(25, 4, lutff_5/in_3)</td></tr>
<tr><td>DATAOUT[7:0]</td><td>(0, 1, slf_op_[7:0])</td><td>(0, 3, slf_op_[7:0])</td><td>(25, 1, slf_op_[7:0])</td><td>(25, 3, slf_op_[7:0])</td></tr>
<tr><td>DATAOUT[15:8]</td><td>(0, 2, slf_op_[7:0])</td><td>(0, 4, slf_op_[7:0])</td><td>(25, 2, slf_op_[7:0])</td><td>(25, 4, slf_op_[7:0])</td></tr>
<tr><td><em>SPRAM_ENABLE</em></td><td><em>(0, 1, CBIT_0)</em></td><td><em>(0, 1, CBIT_1)</em></td><td><em>(25, 1, CBIT_0)</em></td><td><em>(25, 1, CBIT_1)</em></td></tr>
</table>
<h2>RGB LED Driver</h2>
<p>The UltraPlus devices contain an internal 3-channel 2-24mA constant-current driver intended for RGB led driving (<span style="font-family:monospace">SB_RGBA_DRV</span>). It is broken out onto 3 pins: 39, 40 and 41 on the QFN48 package.
The LED driver is implemented using the IPConnect tiles and is entirely seperate to the IO cells, if the LED driver is ignored or disabled on a pin then the pin
can be used as an open-drain IO using the standard IO cell.</p>
<p>Note that the UltraPlus devices also have a seperate PWM generator IP core, which would often be connected to this one to create LED effects such as "breathing" without
involving FPGA resources.</p>
<p>The LED driver connections are shown in the label below.</p>
<table class="ctab">
<tr><th>Signal</th><th>Net</th></tr>
<tr><td>CURREN</td><td>(25, 29, lutff_6/in_3)</td></tr>
<tr><td>RGBLEDEN</td><td>(0, 30, lutff_1/in_1)</td></tr>
<tr><td>RGB0PWM</td><td>(0, 30, lutff_2/in_1)</td></tr>
<tr><td>RGB1PWM</td><td>(0, 30, lutff_3/in_1)</td></tr>
<tr><td>RGB2PWM</td><td>(0, 30, lutff_4/in_1)</td></tr>
</table>
<p>The configuration bits are as follows. As well as the documented bits, another bit <span style="font-family:monospace">RGBA_DRV_EN</span> is set if any of the channels are enabled.</p>
<table class="ctab">
<tr><th>Parameter</th><th>Bit</th></tr>
<tr><td>RGBA_DRV_EN</td><td>(0, 28, CBIT_5)</td></tr>
<tr><td>RGB0_CURRENT[1:0]</td><td>(0, 28, CBIT_[7:6])</td></tr>
<tr><td>RGB0_CURRENT[5:2]</td><td>(0, 29, CBIT_[3:0])</td></tr>
<tr><td>RGB1_CURRENT[3:0]</td><td>(0, 29, CBIT_[7:4])</td></tr>
<tr><td>RGB1_CURRENT[5:4]</td><td>(0, 30, CBIT_[1:0])</td></tr>
<tr><td>RGB2_CURRENT[5:0]</td><td>(0, 30, CBIT_[7:2])</td></tr>
<tr><td>CURRENT_MODE</td><td>(0, 28, CBIT_4)</td></tr>
</table>
<h2>IO Changes</h2>
<p>The IO tiles contain a few new bits compared to earlier ice40 devices.
The bits <span style="font-family:monospace">padeb_test_0</span> and
<span style="font-family:monospace">padeb_test_1</span> are set for all pins,
even unused ones, unless set as an output.</p>
<p>There are also some new bits used to control the pullup strength:</p>
<table class="ctab">
<tr><th>Strength</th><th>Cell 0</th><th>Cell 1</th></tr>
<tr><td>3.3k&Omega;</td><td>cf_bit_32<br/>B7[10]</td><td>cf_bit_36<br/>B13[10]</td></tr>
<tr><td>6.8k&Omega;</td><td>cf_bit_33<br/>B6[10]</td><td>cf_bit_37<br/>B12[10]</td></tr>
<tr><td>10k&Omega;</td><td>cf_bit_34<br/>B7[15]</td><td>cf_bit_38<br/>B13[15]</td></tr>
<tr><td>100k&Omega;<br/>(default)</td><td>!cf_bit_35<br/>!B6[15]</td><td>!cf_bit_39<br/>!B12[15]</td></tr>
</table>
</body></html>

View File

@ -1,4 +0,0 @@
example.bin
example.blif
example.asc
example.rpt

View File

@ -1,10 +0,0 @@
module top (
input btn,
output LED0,
output LED1,
);
assign LED0 = !btn;
assign LED1 = btn;
endmodule

View File

@ -1,3 +0,0 @@
set_io LED0 12
set_io LED1 21
set_io btn 26

12
examples/up5k_mac16/.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
*.bin
*.blif
*.asc
*.rpt
*.glb
*.psb
*.sdf
*.vsb
*.bin
*.tmp/
*.exp
*.vlog

View File

@ -1,12 +1,12 @@
PROJ = example
PIN_DEF = up5k.pcf
PROJ = mac16
PIN_DEF = mac16.pcf
DEVICE = up5k
# Relative paths for easier development without messing with installed version
ARACHNE = ../../../arachne-pnr/bin/arachne-pnr
ARACHNE_ARGS = -c ../../icebox/chipdb-5k.txt
ICEPACK = ../../icepack/icepack
ICETIME = ../../icetime/icetime
ICEPROG = ../../iceprog/iceprog
ARACHNE = arachne-pnr
ARACHNE_ARGS =
ICEPACK = icepack
ICETIME = icetime
ICEPROG = iceprog
all: $(PROJ).bin

View File

@ -0,0 +1,4 @@
set_io clk 44
set_io rstn 27
set_io LED1 12
set_io LED2 13

View File

@ -0,0 +1,71 @@
module top(
input clk,
input rstn,
output LED1,
output LED2);
wire reset = !rstn;
wire [15:0] A = 16'd999;
wire [15:0] B = 16'd12345;
wire [31:0] RES = 32'd12332655;
wire [31:0] dsp_out;
SB_MAC16 i_sbmac16
(
.A(A),
.B(B),
.C(16'b0),
.D(16'b0),
.CLK(clk),
.CE(1'b1),
.IRSTTOP(reset),
.IRSTBOT(reset),
.ORSTTOP(reset),
.ORSTBOT(reset),
.AHOLD(1'b0),
.BHOLD(1'b0),
.CHOLD(1'b0),
.DHOLD(1'b0),
.OHOLDTOP(1'b0),
.OHOLDBOT(1'b0),
.OLOADTOP(1'b0),
.OLOADBOT(1'b0),
.ADDSUBTOP(1'b0),
.ADDSUBBOT(1'b0),
.CO(),
.CI(1'b0),
.O(dsp_out)
);
//16x16 => 32 unsigned pipelined multiply
defparam i_sbmac16. B_SIGNED = 1'b0;
defparam i_sbmac16. A_SIGNED = 1'b0;
defparam i_sbmac16. MODE_8x8 = 1'b0;
defparam i_sbmac16. BOTADDSUB_CARRYSELECT = 2'b00;
defparam i_sbmac16. BOTADDSUB_UPPERINPUT = 1'b0;
defparam i_sbmac16. BOTADDSUB_LOWERINPUT = 2'b00;
defparam i_sbmac16. BOTOUTPUT_SELECT = 2'b11;
defparam i_sbmac16. TOPADDSUB_CARRYSELECT = 2'b00;
defparam i_sbmac16. TOPADDSUB_UPPERINPUT = 1'b0;
defparam i_sbmac16. TOPADDSUB_LOWERINPUT = 2'b00;
defparam i_sbmac16. TOPOUTPUT_SELECT = 2'b11;
defparam i_sbmac16. PIPELINE_16x16_MULT_REG2 = 1'b1;
defparam i_sbmac16. PIPELINE_16x16_MULT_REG1 = 1'b1;
defparam i_sbmac16. BOT_8x8_MULT_REG = 1'b1;
defparam i_sbmac16. TOP_8x8_MULT_REG = 1'b1;
defparam i_sbmac16. D_REG = 1'b0;
defparam i_sbmac16. B_REG = 1'b1;
defparam i_sbmac16. A_REG = 1'b1;
defparam i_sbmac16. C_REG = 1'b0;
assign LED1 = (dsp_out == RES) ? 1'b1 : 1'b0;
assign LED2 = 1'b0;
endmodule

12
examples/up5k_rgb/.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
*.bin
*.blif
*.asc
*.rpt
*.glb
*.psb
*.sdf
*.vsb
*.bin
*.tmp/
*.exp
*.vlog

View File

@ -0,0 +1,36 @@
PROJ = rgb
PIN_DEF = rgb.pcf
DEVICE = up5k
ARACHNE = arachne-pnr
ARACHNE_ARGS =
ICEPACK = icepack
ICETIME = icetime
ICEPROG = iceprog
all: $(PROJ).bin
%.blif: %.v
yosys -p 'synth_ice40 -top top -blif $@' $<
%.asc: $(PIN_DEF) %.blif
$(ARACHNE) $(ARACHNE_ARGS) -d $(subst up,,$(subst hx,,$(subst lp,,$(DEVICE)))) -o $@ -p $^
%.bin: %.asc
$(ICEPACK) $< $@
%.rpt: %.asc
$(ICETIME) -d $(DEVICE) -mtr $@ $<
prog: $(PROJ).bin
$(ICEPROG) -S $<
sudo-prog: $(PROJ).bin
@echo 'Executing prog as root!!!'
sudo $(ICEPROG) -S $<
clean:
rm -f $(PROJ).blif $(PROJ).asc $(PROJ).rpt $(PROJ).bin
.SECONDARY:
.PHONY: all prog clean

View File

@ -0,0 +1,3 @@
set_io RGB0 39
set_io RGB1 40
set_io RGB2 41

81
examples/up5k_rgb/rgb.v Normal file
View File

@ -0,0 +1,81 @@
module top(
output RGB0, RGB1, RGB2
);
wire clk;
SB_HFOSC inthosc (
.CLKHFPU(1'b1),
.CLKHFEN(1'b1),
.CLKHF(clk)
);
localparam counter_width = 32;
reg [counter_width-1:0] ctr;
always@(posedge clk)
begin
ctr <= ctr + 1;
end
localparam pwm_width = 12;
localparam pwm_max = (2**pwm_width) - 1;
localparam pwm_max_div4 = (2**(pwm_width-2)) - 1;
wire [1:0] phase = ctr[counter_width - 1 : counter_width - 2];
wire [pwm_width-1:0] fade = ctr[counter_width - 3 : counter_width - (2 + pwm_width)];
wire [pwm_width-1:0] fade_div4 = ctr[counter_width - 3 : counter_width - (pwm_width)];
wire [pwm_width-1:0] r_val, g_val, b_val;
// Fade R->G->B->W->
assign r_val = (phase == 0) ? pwm_max_div4 + (3 * fade_div4) :
(phase == 1) ? pwm_max - fade :
(phase == 3) ? fade_div4 :
0;
assign g_val = (phase == 0) ? pwm_max_div4 - fade_div4:
(phase == 1) ? fade :
(phase == 2) ? pwm_max - fade :
(phase == 3) ? fade_div4 :
0;
assign b_val = (phase == 0) ? pwm_max_div4 - fade_div4:
(phase == 2) ? fade :
(phase == 3) ? pwm_max - (3 * fade_div4) :
0;
reg [pwm_width-1:0] pwm_ctr;
reg pwm_r, pwm_g, pwm_b;
always@(posedge clk)
begin
pwm_ctr <= pwm_ctr + 1;
pwm_r <= (pwm_ctr < r_val) ? 1'b1 : 1'b0;
pwm_g <= (pwm_ctr < g_val) ? 1'b1 : 1'b0;
pwm_b <= (pwm_ctr < b_val) ? 1'b1 : 1'b0;
end
SB_RGBA_DRV RGBA_DRIVER (
.CURREN(1'b1),
.RGBLEDEN(1'b1),
.RGB0PWM(pwm_g),
.RGB1PWM(pwm_b),
.RGB2PWM(pwm_r),
.RGB0(RGB0),
.RGB1(RGB1),
.RGB2(RGB2)
);
defparam RGBA_DRIVER.CURRENT_MODE = "0b1";
defparam RGBA_DRIVER.RGB0_CURRENT = "0b000111";
defparam RGBA_DRIVER.RGB1_CURRENT = "0b000111";
defparam RGBA_DRIVER.RGB2_CURRENT = "0b000111";
endmodule

View File

@ -1,6 +1,6 @@
include ../config.mk
all: chipdb-384.txt chipdb-1k.txt chipdb-8k.txt
all: chipdb-384.txt chipdb-1k.txt chipdb-8k.txt chipdb-5k.txt
chipdb-384.txt: icebox.py iceboxdb.py icebox_chipdb.py
python3 icebox_chipdb.py -3 > chipdb-384.new
@ -33,6 +33,7 @@ install: all
cp chipdb-384.txt $(DESTDIR)$(PREFIX)/share/icebox/
cp chipdb-1k.txt $(DESTDIR)$(PREFIX)/share/icebox/
cp chipdb-8k.txt $(DESTDIR)$(PREFIX)/share/icebox/
cp chipdb-5k.txt $(DESTDIR)$(PREFIX)/share/icebox/
cp icebox.py $(DESTDIR)$(PREFIX)/bin/icebox.py
cp iceboxdb.py $(DESTDIR)$(PREFIX)/bin/iceboxdb.py
cp icebox_chipdb.py $(DESTDIR)$(PREFIX)/bin/icebox_chipdb$(PY_EXE)

View File

@ -31,6 +31,8 @@ class iceconfig:
self.io_tiles = dict()
self.ramb_tiles = dict()
self.ramt_tiles = dict()
self.dsp_tiles = [dict() for i in range(4)]
self.ipcon_tiles = dict()
self.ram_data = dict()
self.extra_bits = set()
self.symbols = dict()
@ -96,7 +98,18 @@ class iceconfig:
for x in range(1, self.max_x):
self.io_tiles[(x, 0)] = ["0" * 18 for i in range(16)]
self.io_tiles[(x, self.max_y)] = ["0" * 18 for i in range(16)]
for x in [0, self.max_x]:
for y in range(1, self.max_y):
if y in [5, 10, 15, 23]:
self.dsp_tiles[0][(x, y)] = ["0" * 54 for i in range(16)]
elif y in [6, 11, 16, 24]:
self.dsp_tiles[1][(x, y)] = ["0" * 54 for i in range(16)]
elif y in [7, 12, 17, 25]:
self.dsp_tiles[2][(x, y)] = ["0" * 54 for i in range(16)]
elif y in [8, 13, 18, 26]:
self.dsp_tiles[3][(x, y)] = ["0" * 54 for i in range(16)]
else:
self.ipcon_tiles[(x, y)] = ["0" * 54 for i in range(16)]
def setup_empty_8k(self):
self.clear()
self.device = "8k"
@ -132,6 +145,9 @@ class iceconfig:
if (x, y) in self.logic_tiles: return self.logic_tiles[(x, y)]
if (x, y) in self.ramb_tiles: return self.ramb_tiles[(x, y)]
if (x, y) in self.ramt_tiles: return self.ramt_tiles[(x, y)]
for i in range(4):
if (x, y) in self.dsp_tiles[i]: return self.dsp_tiles[i][(x, y)]
if (x, y) in self.ipcon_tiles: return self.ipcon_tiles[(x, y)]
return None
def pinloc_db(self):
@ -166,7 +182,12 @@ class iceconfig:
if self.device == "384":
return [ ]
assert False
# Return true if device is Ultra/UltraPlus series, i.e. has
# IpConnect/DSP at the sides instead of IO
def is_ultra(self):
return self.device in ["5k"]
def colbuf_db(self):
if self.device == "1k":
entries = list()
@ -221,7 +242,64 @@ class iceconfig:
return entries
assert False
# Return a map between HDL name and routing net and location for a given DSP cell
def get_dsp_nets_db(self, x, y):
assert ((x, y) in self.dsp_tiles[0])
# Control signals
nets = {
"CLK": (x, y+2, "lutff_global/clk"),
"CE": (x, y+2, "lutff_global/cen"),
"IRSTTOP": (x, y+1, "lutff_global/s_r"),
"IRSTBOT": (x, y+0, "lutff_global/s_r"),
"ORSTTOP": (x, y+3, "lutff_global/s_r"),
"ORSTBOT": (x, y+2, "lutff_global/s_r"),
"AHOLD": (x, y+2, "lutff_0/in_0"),
"BHOLD": (x, y+1, "lutff_0/in_0"),
"CHOLD": (x, y+3, "lutff_0/in_0"),
"DHOLD": (x, y+0, "lutff_0/in_0"),
"OHOLDTOP": (x, y+3, "lutff_1/in_0"),
"OHOLDBOT": (x, y+0, "lutff_1/in_0"),
"ADDSUBTOP": (x, y+3, "lutff_3/in_0"),
"ADDSUBBOT": (x, y+0, "lutff_3/in_0"),
"OLOADTOP": (x, y+3, "lutff_2/in_0"),
"OLOADBOT": (x, y+0, "lutff_2/in_0"),
"CI": (x, y+0, "lutff_4/in_0"),
"CO": (x, y+4, "slf_op_0")
}
#Data ports
for i in range(8):
nets["C_%d" % i] = (x, y+3, "lutff_%d/in_3" % i)
nets["C_%d" % (i+8)] = (x, y+3, "lutff_%d/in_1" % i)
nets["A_%d" % i] = (x, y+2, "lutff_%d/in_3" % i)
nets["A_%d" % (i+8)] = (x, y+2, "lutff_%d/in_1" % i)
nets["B_%d" % i] = (x, y+1, "lutff_%d/in_3" % i)
nets["B_%d" % (i+8)] = (x, y+1, "lutff_%d/in_1" % i)
nets["D_%d" % i] = (x, y+0, "lutff_%d/in_3" % i)
nets["D_%d" % (i+8)] = (x, y+0, "lutff_%d/in_1" % i)
for i in range(32):
nets["O_%d" % i] = (x, y+(i//8), "mult/O_%d" % i)
return nets
# Return the location of configuration bits for a given DSP cell
def get_dsp_config_db(self, x, y):
assert ((x, y) in self.dsp_tiles[0])
override = { }
if (("%s_%d_%d" % (self.device, x, y)) in dsp_config_db):
override = dsp_config_db["%s_%d_%d" % (self.device, x, y)]
default_db = dsp_config_db["default"]
merged = { }
for cfgkey in default_db:
cx, cy, cbit = default_db[cfgkey]
if cfgkey in override:
cx, cy, cbit = override[cfgkey]
merged[cfgkey] = (x + cx, y + cy, cbit)
return merged
def tile_db(self, x, y):
# Only these devices have IO on the left and right sides.
if self.device in ["384", "1k", "8k"]:
@ -242,6 +320,12 @@ class iceconfig:
if (x, y) in self.logic_tiles: return logictile_5k_db
if (x, y) in self.ramb_tiles: return rambtile_5k_db
if (x, y) in self.ramt_tiles: return ramttile_5k_db
if (x, y) in self.ipcon_tiles: return ipcon_5k_db
if (x, y) in self.dsp_tiles[0]: return dsp0_5k_db
if (x, y) in self.dsp_tiles[1]: return dsp1_5k_db
if (x, y) in self.dsp_tiles[2]: return dsp2_5k_db
if (x, y) in self.dsp_tiles[3]: return dsp3_5k_db
elif self.device == "8k":
if (x, y) in self.logic_tiles: return logictile_8k_db
if (x, y) in self.ramb_tiles: return rambtile_8k_db
@ -253,13 +337,24 @@ class iceconfig:
assert False
def tile_type(self, x, y):
if x == 0: return "IO"
if x == 0 and (not self.is_ultra()): return "IO"
if y == 0: return "IO"
if x == self.max_x: return "IO"
if x == self.max_x and (not self.is_ultra()): return "IO"
if y == self.max_y: return "IO"
if (x, y) in self.ramb_tiles: return "RAMB"
if (x, y) in self.ramt_tiles: return "RAMT"
if (x, y) in self.logic_tiles: return "LOGIC"
if (x == 0 or x == self.max_x) and self.is_ultra():
if y in [5, 10, 15, 23]:
return "DSP0"
elif y in [6, 11, 16, 24]:
return "DSP1"
elif y in [7, 12, 17, 25]:
return "DSP2"
elif y in [8, 13, 18, 26]:
return "DSP3"
else:
return "IPCON"
assert False
def tile_pos(self, x, y):
@ -280,25 +375,25 @@ class iceconfig:
if netname.startswith("logic_op_bot_"):
if y == self.max_y and 0 < x < self.max_x: return True
if netname.startswith("logic_op_bnl_"):
if x == self.max_x and 1 < y < self.max_y: return True
if x == self.max_x and 1 < y < self.max_y and (not self.is_ultra()): return True
if y == self.max_y and 1 < x < self.max_x: return True
if netname.startswith("logic_op_bnr_"):
if x == 0 and 1 < y < self.max_y: return True
if x == 0 and 1 < y < self.max_y and (not self.is_ultra()): return True
if y == self.max_y and 0 < x < self.max_x-1: return True
if netname.startswith("logic_op_top_"):
if y == 0 and 0 < x < self.max_x: return True
if netname.startswith("logic_op_tnl_"):
if x == self.max_x and 0 < y < self.max_y-1: return True
if x == self.max_x and 0 < y < self.max_y-1 and (not self.is_ultra()): return True
if y == 0 and 1 < x < self.max_x: return True
if netname.startswith("logic_op_tnr_"):
if x == 0 and 0 < y < self.max_y-1: return True
if x == 0 and 0 < y < self.max_y-1 and (not self.is_ultra()): return True
if y == 0 and 0 < x < self.max_x-1: return True
if netname.startswith("logic_op_lft_"):
if x == self.max_x: return True
if x == self.max_x and (not self.is_ultra()): return True
if netname.startswith("logic_op_rgt_"):
if x == 0: return True
if x == 0 and (not self.is_ultra()): return True
return False
@ -307,16 +402,22 @@ class iceconfig:
return pos_has_net(self.tile_pos(x, y), netname)
def tile_follow_net(self, x, y, direction, netname):
if x == 1 and y not in (0, self.max_y) and direction == 'l': return pos_follow_net("x", "L", netname)
if y == 1 and x not in (0, self.max_x) and direction == 'b': return pos_follow_net("x", "B", netname)
if x == self.max_x-1 and y not in (0, self.max_y) and direction == 'r': return pos_follow_net("x", "R", netname)
if y == self.max_y-1 and x not in (0, self.max_x) and direction == 't': return pos_follow_net("x", "T", netname)
return pos_follow_net(self.tile_pos(x, y), direction, netname)
if x == 1 and y not in (0, self.max_y) and direction == 'l': return pos_follow_net("x", "L", netname, self.is_ultra())
if y == 1 and x not in (0, self.max_x) and direction == 'b': return pos_follow_net("x", "B", netname, self.is_ultra())
if x == self.max_x-1 and y not in (0, self.max_y) and direction == 'r': return pos_follow_net("x", "R", netname, self.is_ultra())
if y == self.max_y-1 and x not in (0, self.max_x) and direction == 't': return pos_follow_net("x", "T", netname, self.is_ultra())
if self.is_ultra(): # Pass through corner positions as they must be handled differently
if y == 1 and x in (0, self.max_x) and direction == 'b': return pos_follow_net(self.tile_pos(x, y), "B", netname, self.is_ultra())
if y == self.max_y-1 and x in (0, self.max_x) and direction == 't': return pos_follow_net(self.tile_pos(x, y), "T", netname, self.is_ultra())
if x == 1 and y in (0, self.max_y) and direction == 'l': return pos_follow_net(self.tile_pos(x, y), "L", netname, self.is_ultra())
if x == self.max_x-1 and y in (0, self.max_y) and direction == 'r': return pos_follow_net(self.tile_pos(x, y), "R", netname, self.is_ultra())
return pos_follow_net(self.tile_pos(x, y), direction, netname, self.is_ultra())
def follow_funcnet(self, x, y, func):
neighbours = set()
def do_direction(name, nx, ny):
if 0 < nx < self.max_x and 0 < ny < self.max_y:
if (0 < nx < self.max_x or self.is_ultra()) and 0 < ny < self.max_y:
neighbours.add((nx, ny, "neigh_op_%s_%d" % (name, func)))
if nx in (0, self.max_x) and 0 < ny < self.max_y and nx != x:
neighbours.add((nx, ny, "logic_op_%s_%d" % (name, func)))
@ -340,6 +441,9 @@ class iceconfig:
if npos == "x":
if (nx, ny) in self.logic_tiles:
return (nx, ny, "lutff_%d/out" % func)
for i in range(4):
if (nx, ny) in self.dsp_tiles[i]: #TODO: check this
return (nx, ny, "mult/O_%d" % (i * 8 + func))
if (nx, ny) in self.ramb_tiles:
if self.device == "1k":
return (nx, ny, "ram/RDATA_%d" % func)
@ -402,7 +506,53 @@ class iceconfig:
assert False
return funcnets
#UltraPlus corner routing: given the corner name and net index,
#return a tuple containing H and V indexes, or none if NA
def ultraplus_trace_corner(self, corner, idx):
h_idx = None
v_idx = None
if corner == "bl":
if idx >= 4:
v_idx = idx + 28
if idx >= 32 and idx < 48:
h_idx = idx - 28
elif corner == "tl":
#TODO: bounds check for v_idx case?
if idx >= 4:
v_idx = (idx + 8) ^ 1
if idx >= 12 and idx < 28:
h_idx = (idx ^ 1) - 8
elif corner == "tr":
#TODO: bounds check for v_idx case?
if idx <= 16:
v_idx = (idx + 12) ^ 1
if idx >= 12 and idx < 28:
h_idx = (idx ^ 1) - 12
elif corner == "br":
#TODO: bounds check for v_idx case?
if idx <= 16:
v_idx = idx + 32
if idx >= 32 and idx < 48: #check
h_idx = idx - 32
return (h_idx, v_idx)
def get_corner(self, x, y):
corner = ""
if y == 0:
corner += "b"
elif y == self.max_y:
corner += "t"
else:
corner += "x"
if x == 0:
corner += "l"
elif x == self.max_x:
corner += "r"
else:
corner += "x"
return corner
def follow_net(self, netspec):
x, y, netname = netspec
neighbours = self.rlookup_funcnet(x, y, netname)
@ -423,12 +573,12 @@ class iceconfig:
neighbours.add((nx, ny, netname))
match = re.match(r"sp4_r_v_b_(\d+)", netname)
if match and 0 < x < self.max_x-1:
if match and ((0 < x < self.max_x-1) or (self.is_ultra() and (x < self.max_x))):
neighbours.add((x+1, y, sp4v_normalize("sp4_v_b_" + match.group(1))))
#print('\tafter r_v_b', neighbours)
match = re.match(r"sp4_v_[bt]_(\d+)", netname)
if match and 1 < x < self.max_x:
if match and (1 < x < self.max_x or (self.is_ultra() and (x > 0))):
n = sp4v_normalize(netname, "b")
if n is not None:
n = n.replace("sp4_", "sp4_r_")
@ -459,9 +609,36 @@ class iceconfig:
if s[0] in (0, self.max_x) and s[1] in (0, self.max_y):
if re.match("span4_(vert|horz)_[lrtb]_\d+$", n):
m = re.match("span4_(vert|horz)_([lrtb])_\d+$", n)
#We ignore L and T edges when performing the Ultra/UltraPlus corner algorithm
if self.is_ultra() and (m.group(2) == "l" or m.group(2) == "t"):
continue
vert_net = n.replace("_l_", "_t_").replace("_r_", "_b_").replace("_horz_", "_vert_")
horz_net = n.replace("_t_", "_l_").replace("_b_", "_r_").replace("_vert_", "_horz_")
if self.is_ultra(): #Convert between span4 and sp4, and perform U/UP corner tracing
m = re.match("span4_vert_([lrtb])_(\d+)$", vert_net)
assert m
idx = int(m.group(2))
h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
if v_idx is None:
if (s[0] == 0 and s[1] == 0 and direction == "l") or (s[0] == self.max_x and s[1] == self.max_y and direction == "r"):
continue #Not routed, skip
else:
vert_net = "sp4_v_%s_%d" % (m.group(1), v_idx)
m = re.match("span4_horz_([lrtb])_(\d+)$", horz_net)
assert m
idx = int(m.group(2))
h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
if h_idx is None:
if (s[0] == 0 and s[1] == 0 and direction == "b") or (s[0] == self.max_x and s[1] == self.max_y and direction == "t"):
continue #Not routed, skip
else:
horz_net = "span4_horz_%s_%d" % (m.group(1), h_idx)
if s[0] == 0 and s[1] == 0:
if direction == "l": s = (0, 1, vert_net)
if direction == "b": s = (1, 0, horz_net)
@ -473,6 +650,30 @@ class iceconfig:
vert_net = netname.replace("_l_", "_t_").replace("_r_", "_b_").replace("_horz_", "_vert_")
horz_net = netname.replace("_t_", "_l_").replace("_b_", "_r_").replace("_vert_", "_horz_")
if self.is_ultra():
# Might have sp4 not span4 here
vert_net = vert_net.replace("_h_", "_v_")
horz_net = horz_net.replace("_v_", "_h_")
m = re.match("(span4_vert|sp4_v)_([lrtb])_(\d+)$", vert_net)
assert m
idx = int(m.group(3))
h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
if v_idx is None:
if (s[0] == 0 and s[1] == self.max_y and direction == "l") or (s[0] == self.max_x and s[1] == 0 and direction == "r"):
continue
else:
vert_net = "sp4_v_%s_%d" % (m.group(2), v_idx)
m = re.match("(span4_horz|sp4_h)_([lrtb])_(\d+)$", horz_net)
assert m
idx = int(m.group(3))
h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
if h_idx is None:
if (s[0] == 0 and s[1] == self.max_y and direction == "t") or (s[0] == self.max_x and s[1] == 0 and direction == "b"):
continue
else:
horz_net = "span4_horz_%s_%d" % (m.group(2), h_idx)
if s[0] == 0 and s[1] == self.max_y:
if direction == "l": s = (0, self.max_y-1, vert_net)
if direction == "t": s = (1, self.max_y, horz_net)
@ -566,7 +767,22 @@ class iceconfig:
add_seed_segments(idx, tile, ramttile_8k_db)
else:
assert False
for idx, tile in self.dsp_tiles[0].items():
if self.device == "5k":
add_seed_segments(idx, tile, dsp0_5k_db)
for idx, tile in self.dsp_tiles[1].items():
if self.device == "5k":
add_seed_segments(idx, tile, dsp1_5k_db)
for idx, tile in self.dsp_tiles[2].items():
if self.device == "5k":
add_seed_segments(idx, tile, dsp2_5k_db)
for idx, tile in self.dsp_tiles[3].items():
if self.device == "5k":
add_seed_segments(idx, tile, dsp3_5k_db)
for idx, tile in self.ipcon_tiles.items():
if self.device == "5k":
add_seed_segments(idx, tile, ipcon_5k_db)
for padin, pio in enumerate(self.padin_pio_db()):
s1 = (pio[0], pio[1], "padin_%d" % pio[2])
s2 = (pio[0], pio[1], "glb_netwk_%d" % padin)
@ -661,7 +877,7 @@ class iceconfig:
expected_data_lines -= 1
continue
assert expected_data_lines <= 0
if line[0] in (".io_tile", ".logic_tile", ".ramb_tile", ".ramt_tile", ".ram_data", ".ipconn_tile", ".dsp1_tile", ".dsp2_tile", ".dsp3_tile", ".dsp4_tile"):
if line[0] in (".io_tile", ".logic_tile", ".ramb_tile", ".ramt_tile", ".ram_data", ".ipcon_tile", ".dsp0_tile", ".dsp1_tile", ".dsp2_tile", ".dsp3_tile"):
current_data = list()
expected_data_lines = 16
self.max_x = max(self.max_x, int(line[1]))
@ -678,6 +894,13 @@ class iceconfig:
if line[0] == ".ramt_tile":
self.ramt_tiles[(int(line[1]), int(line[2]))] = current_data
continue
if line[0] == ".ipcon_tile":
self.ipcon_tiles[(int(line[1]), int(line[2]))] = current_data
continue
match = re.match(r".dsp(\d)_tile", line[0])
if match:
self.dsp_tiles[int(match.group(1))][(int(line[1]), int(line[2]))] = current_data
continue
if line[0] == ".ram_data":
self.ram_data[(int(line[1]), int(line[2]))] = current_data
continue
@ -862,6 +1085,8 @@ def netname_normalize(netname, edge="", ramb=False, ramt=False, ramb_8k=False, r
netname = netname.replace("lc_", "lutff_")
netname = netname.replace("wire_logic_cluster/", "")
netname = netname.replace("wire_io_cluster/", "")
netname = netname.replace("wire_mult/", "")
netname = netname.replace("wire_con_box/", "")
netname = netname.replace("wire_bram/", "")
if (ramb or ramt or ramb_8k or ramt_8k) and netname.startswith("input"):
match = re.match(r"input(\d)_(\d)", netname)
@ -871,7 +1096,7 @@ def netname_normalize(netname, edge="", ramb=False, ramt=False, ramb_8k=False, r
if ramb_8k: netname="ram/RADDR_%d" % ([7, 6, 5, 4, 3, 2, 1, 0, -1, -1, -1, -1, -1, 10, 9, 8][idx1*4 + idx2])
if ramt_8k: netname="ram/WADDR_%d" % ([7, 6, 5, 4, 3, 2, 1, 0, -1, -1, -1, -1, -1, 10, 9, 8][idx1*4 + idx2])
match = re.match(r"(...)_op_(.*)", netname)
if match:
if match and (match.group(1) != "slf"):
netname = "neigh_op_%s_%s" % (match.group(1), match.group(2))
if re.match(r"lutff_7/(cen|clk|s_r)", netname):
netname = netname.replace("lutff_7/", "lutff_global/")
@ -890,13 +1115,13 @@ def pos_has_net(pos, netname):
if re.search(r"_vert_[bt]_\d+$", netname): return False
return True
def pos_follow_net(pos, direction, netname):
if pos == "x":
def pos_follow_net(pos, direction, netname, is_ultra):
if pos == "x" or ((pos in ("l", "r")) and is_ultra):
m = re.match("sp4_h_[lr]_(\d+)$", netname)
if m and direction in ("l", "L"):
n = sp4h_normalize(netname, "l")
if n is not None:
if direction == "l":
if direction == "l" or is_ultra:
n = re.sub("_l_", "_r_", n)
n = sp4h_normalize(n)
else:
@ -906,7 +1131,7 @@ def pos_follow_net(pos, direction, netname):
if m and direction in ("r", "R"):
n = sp4h_normalize(netname, "r")
if n is not None:
if direction == "r":
if direction == "r" or is_ultra:
n = re.sub("_r_", "_l_", n)
n = sp4h_normalize(n)
else:
@ -916,6 +1141,8 @@ def pos_follow_net(pos, direction, netname):
m = re.match("sp4_v_[tb]_(\d+)$", netname)
if m and direction in ("t", "T"):
if is_ultra and direction == "T" and pos in ("l", "r"):
return re.sub("sp4_v_", "span4_vert_", netname)
n = sp4v_normalize(netname, "t")
if n is not None:
if direction == "t":
@ -926,6 +1153,8 @@ def pos_follow_net(pos, direction, netname):
n = re.sub("sp4_v_", "span4_vert_", n)
return n
if m and direction in ("b", "B"):
if is_ultra and direction == "B" and pos in ("l", "r"):
return re.sub("sp4_v_", "span4_vert_", netname)
n = sp4v_normalize(netname, "b")
if n is not None:
if direction == "b":
@ -940,7 +1169,7 @@ def pos_follow_net(pos, direction, netname):
if m and direction in ("l", "L"):
n = sp12h_normalize(netname, "l")
if n is not None:
if direction == "l":
if direction == "l" or is_ultra:
n = re.sub("_l_", "_r_", n)
n = sp12h_normalize(n)
else:
@ -950,7 +1179,7 @@ def pos_follow_net(pos, direction, netname):
if m and direction in ("r", "R"):
n = sp12h_normalize(netname, "r")
if n is not None:
if direction == "r":
if direction == "r" or is_ultra:
n = re.sub("_r_", "_l_", n)
n = sp12h_normalize(n)
else:
@ -980,7 +1209,7 @@ def pos_follow_net(pos, direction, netname):
n = re.sub("sp12_v_", "span12_vert_", n)
return n
if pos in ("l", "r" ):
if (pos in ("l", "r" )) and (not is_ultra):
m = re.match("span4_vert_([bt])_(\d+)$", netname)
if m:
case, idx = direction + m.group(1), int(m.group(2))
@ -997,6 +1226,8 @@ def pos_follow_net(pos, direction, netname):
m = re.match("span4_horz_([rl])_(\d+)$", netname)
if m:
case, idx = direction + m.group(1), int(m.group(2))
if direction == "L" or direction == "R":
return netname
if case == "ll":
return "span4_horz_r_%d" % idx
if case == "lr" and idx >= 4:
@ -1006,13 +1237,13 @@ def pos_follow_net(pos, direction, netname):
if case == "rr" and idx >= 12:
return "span4_horz_l_%d" % idx
if pos == "l" and direction == "r":
if pos == "l" and direction == "r" and (not is_ultra):
m = re.match("span4_horz_(\d+)$", netname)
if m: return sp4h_normalize("sp4_h_l_%s" % m.group(1))
m = re.match("span12_horz_(\d+)$", netname)
if m: return sp12h_normalize("sp12_h_l_%s" % m.group(1))
if pos == "r" and direction == "l":
if pos == "r" and direction == "l" and (not is_ultra):
m = re.match("span4_horz_(\d+)$", netname)
if m: return sp4h_normalize("sp4_h_r_%s" % m.group(1))
m = re.match("span12_horz_(\d+)$", netname)
@ -1086,7 +1317,7 @@ def run_checks_neigh():
if x in (0, ic.max_x) and y in (0, ic.max_y):
continue
# Skip the sides of a 5k device.
if ic.device == "5k" and x in (0, ic.max_x):
if self.is_ultra() and x in (0, ic.max_x):
continue
add_segments((x, y), ic.tile_db(x, y))
if (x, y) in ic.logic_tiles:
@ -4167,6 +4398,340 @@ pinloc_db = {
],
}
# This database contains the locations of configuration bits of the DSP tiles
# The standard configuration is stored under the key "default". If it is necessary to
# override it for a certain DSP on a certain device use the key "{device}_{x}_{y}" where
# {x} and {y} are the location of the DSP0 tile of the DSP (NOT the tile the cbit is in).
# x and y are relative to the DSP0 tile.
dsp_config_db = {
"default" : {
"C_REG": (0, 0, "CBIT_0"),
"A_REG": (0, 0, "CBIT_1"),
"B_REG": (0, 0, "CBIT_2"),
"D_REG": (0, 0, "CBIT_3"),
"TOP_8x8_MULT_REG": (0, 0, "CBIT_4"),
"BOT_8x8_MULT_REG": (0, 0, "CBIT_5"),
"PIPELINE_16x16_MULT_REG1": (0, 0, "CBIT_6"),
"PIPELINE_16x16_MULT_REG2": (0, 0, "CBIT_7"),
"TOPOUTPUT_SELECT_0": (0, 1, "CBIT_0"),
"TOPOUTPUT_SELECT_1": (0, 1, "CBIT_1"),
"TOPADDSUB_LOWERINPUT_0": (0, 1, "CBIT_2"),
"TOPADDSUB_LOWERINPUT_1": (0, 1, "CBIT_3"),
"TOPADDSUB_UPPERINPUT": (0, 1, "CBIT_4"),
"TOPADDSUB_CARRYSELECT_0": (0, 1, "CBIT_5"),
"TOPADDSUB_CARRYSELECT_1": (0, 1, "CBIT_6"),
"BOTOUTPUT_SELECT_0": (0, 1, "CBIT_7"),
"BOTOUTPUT_SELECT_1": (0, 2, "CBIT_0"),
"BOTADDSUB_LOWERINPUT_0": (0, 2, "CBIT_1"),
"BOTADDSUB_LOWERINPUT_1": (0, 2, "CBIT_2"),
"BOTADDSUB_UPPERINPUT": (0, 2, "CBIT_3"),
"BOTADDSUB_CARRYSELECT_0": (0, 2, "CBIT_4"),
"BOTADDSUB_CARRYSELECT_1": (0, 2, "CBIT_5"),
"MODE_8x8": (0, 2, "CBIT_6"),
"A_SIGNED": (0, 2, "CBIT_7"),
"B_SIGNED": (0, 3, "CBIT_0")
},
"5k_0_15": {
"TOPOUTPUT_SELECT_1": (0, 4, "CBIT_3"),
"TOPADDSUB_LOWERINPUT_0": (0, 4, "CBIT_4"),
"TOPADDSUB_LOWERINPUT_1": (0, 4, "CBIT_5"),
"TOPADDSUB_UPPERINPUT": (0, 4, "CBIT_6")
}
}
# SPRAM data for UltraPlus devices, use icefuzz/tests/fuzz_spram.py
# to generate this
spram_db = {
"5k" : {
(0, 0, 1): {
"ADDRESS_0": (0, 2, "lutff_0/in_1"),
"ADDRESS_10": (0, 2, "lutff_2/in_0"),
"ADDRESS_11": (0, 2, "lutff_3/in_0"),
"ADDRESS_12": (0, 2, "lutff_4/in_0"),
"ADDRESS_13": (0, 2, "lutff_5/in_0"),
"ADDRESS_1": (0, 2, "lutff_1/in_1"),
"ADDRESS_2": (0, 2, "lutff_2/in_1"),
"ADDRESS_3": (0, 2, "lutff_3/in_1"),
"ADDRESS_4": (0, 2, "lutff_4/in_1"),
"ADDRESS_5": (0, 2, "lutff_5/in_1"),
"ADDRESS_6": (0, 2, "lutff_6/in_1"),
"ADDRESS_7": (0, 2, "lutff_7/in_1"),
"ADDRESS_8": (0, 2, "lutff_0/in_0"),
"ADDRESS_9": (0, 2, "lutff_1/in_0"),
"CHIPSELECT": (0, 3, "lutff_6/in_1"),
"CLOCK": (0, 1, "clk"),
"DATAIN_0": (0, 1, "lutff_0/in_3"),
"DATAIN_10": (0, 1, "lutff_2/in_1"),
"DATAIN_11": (0, 1, "lutff_3/in_1"),
"DATAIN_12": (0, 1, "lutff_4/in_1"),
"DATAIN_13": (0, 1, "lutff_5/in_1"),
"DATAIN_14": (0, 1, "lutff_6/in_1"),
"DATAIN_15": (0, 1, "lutff_7/in_1"),
"DATAIN_1": (0, 1, "lutff_1/in_3"),
"DATAIN_2": (0, 1, "lutff_2/in_3"),
"DATAIN_3": (0, 1, "lutff_3/in_3"),
"DATAIN_4": (0, 1, "lutff_4/in_3"),
"DATAIN_5": (0, 1, "lutff_5/in_3"),
"DATAIN_6": (0, 1, "lutff_6/in_3"),
"DATAIN_7": (0, 1, "lutff_7/in_3"),
"DATAIN_8": (0, 1, "lutff_0/in_1"),
"DATAIN_9": (0, 1, "lutff_1/in_1"),
"DATAOUT_0": (0, 1, "slf_op_0"),
"DATAOUT_10": (0, 2, "slf_op_2"),
"DATAOUT_11": (0, 2, "slf_op_3"),
"DATAOUT_12": (0, 2, "slf_op_4"),
"DATAOUT_13": (0, 2, "slf_op_5"),
"DATAOUT_14": (0, 2, "slf_op_6"),
"DATAOUT_15": (0, 2, "slf_op_7"),
"DATAOUT_1": (0, 1, "slf_op_1"),
"DATAOUT_2": (0, 1, "slf_op_2"),
"DATAOUT_3": (0, 1, "slf_op_3"),
"DATAOUT_4": (0, 1, "slf_op_4"),
"DATAOUT_5": (0, 1, "slf_op_5"),
"DATAOUT_6": (0, 1, "slf_op_6"),
"DATAOUT_7": (0, 1, "slf_op_7"),
"DATAOUT_8": (0, 2, "slf_op_0"),
"DATAOUT_9": (0, 2, "slf_op_1"),
"MASKWREN_0": (0, 3, "lutff_0/in_0"),
"MASKWREN_1": (0, 3, "lutff_1/in_0"),
"MASKWREN_2": (0, 3, "lutff_2/in_0"),
"MASKWREN_3": (0, 3, "lutff_3/in_0"),
"POWEROFF": (0, 4, "lutff_4/in_3"),
"SLEEP": (0, 4, "lutff_2/in_3"),
"SPRAM_EN": (0, 1, "CBIT_0"),
"STANDBY": (0, 4, "lutff_0/in_3"),
"WREN": (0, 3, "lutff_4/in_1"),
},
(0, 0, 2): {
"ADDRESS_0": (0, 2, "lutff_6/in_0"),
"ADDRESS_10": (0, 3, "lutff_0/in_1"),
"ADDRESS_11": (0, 3, "lutff_1/in_1"),
"ADDRESS_12": (0, 3, "lutff_2/in_1"),
"ADDRESS_13": (0, 3, "lutff_3/in_1"),
"ADDRESS_1": (0, 2, "lutff_7/in_0"),
"ADDRESS_2": (0, 3, "lutff_0/in_3"),
"ADDRESS_3": (0, 3, "lutff_1/in_3"),
"ADDRESS_4": (0, 3, "lutff_2/in_3"),
"ADDRESS_5": (0, 3, "lutff_3/in_3"),
"ADDRESS_6": (0, 3, "lutff_4/in_3"),
"ADDRESS_7": (0, 3, "lutff_5/in_3"),
"ADDRESS_8": (0, 3, "lutff_6/in_3"),
"ADDRESS_9": (0, 3, "lutff_7/in_3"),
"CHIPSELECT": (0, 3, "lutff_7/in_1"),
"CLOCK": (0, 2, "clk"),
"DATAIN_0": (0, 1, "lutff_0/in_0"),
"DATAIN_10": (0, 2, "lutff_2/in_3"),
"DATAIN_11": (0, 2, "lutff_3/in_3"),
"DATAIN_12": (0, 2, "lutff_4/in_3"),
"DATAIN_13": (0, 2, "lutff_5/in_3"),
"DATAIN_14": (0, 2, "lutff_6/in_3"),
"DATAIN_15": (0, 2, "lutff_7/in_3"),
"DATAIN_1": (0, 1, "lutff_1/in_0"),
"DATAIN_2": (0, 1, "lutff_2/in_0"),
"DATAIN_3": (0, 1, "lutff_3/in_0"),
"DATAIN_4": (0, 1, "lutff_4/in_0"),
"DATAIN_5": (0, 1, "lutff_5/in_0"),
"DATAIN_6": (0, 1, "lutff_6/in_0"),
"DATAIN_7": (0, 1, "lutff_7/in_0"),
"DATAIN_8": (0, 2, "lutff_0/in_3"),
"DATAIN_9": (0, 2, "lutff_1/in_3"),
"DATAOUT_0": (0, 3, "slf_op_0"),
"DATAOUT_10": (0, 4, "slf_op_2"),
"DATAOUT_11": (0, 4, "slf_op_3"),
"DATAOUT_12": (0, 4, "slf_op_4"),
"DATAOUT_13": (0, 4, "slf_op_5"),
"DATAOUT_14": (0, 4, "slf_op_6"),
"DATAOUT_15": (0, 4, "slf_op_7"),
"DATAOUT_1": (0, 3, "slf_op_1"),
"DATAOUT_2": (0, 3, "slf_op_2"),
"DATAOUT_3": (0, 3, "slf_op_3"),
"DATAOUT_4": (0, 3, "slf_op_4"),
"DATAOUT_5": (0, 3, "slf_op_5"),
"DATAOUT_6": (0, 3, "slf_op_6"),
"DATAOUT_7": (0, 3, "slf_op_7"),
"DATAOUT_8": (0, 4, "slf_op_0"),
"DATAOUT_9": (0, 4, "slf_op_1"),
"MASKWREN_0": (0, 3, "lutff_4/in_0"),
"MASKWREN_1": (0, 3, "lutff_5/in_0"),
"MASKWREN_2": (0, 3, "lutff_6/in_0"),
"MASKWREN_3": (0, 3, "lutff_7/in_0"),
"POWEROFF": (0, 4, "lutff_5/in_3"),
"SLEEP": (0, 4, "lutff_3/in_3"),
"SPRAM_EN": (0, 1, "CBIT_1"),
"STANDBY": (0, 4, "lutff_1/in_3"),
"WREN": (0, 3, "lutff_5/in_1"),
},
(25, 0, 3): {
"ADDRESS_0": (25, 2, "lutff_0/in_1"),
"ADDRESS_10": (25, 2, "lutff_2/in_0"),
"ADDRESS_11": (25, 2, "lutff_3/in_0"),
"ADDRESS_12": (25, 2, "lutff_4/in_0"),
"ADDRESS_13": (25, 2, "lutff_5/in_0"),
"ADDRESS_1": (25, 2, "lutff_1/in_1"),
"ADDRESS_2": (25, 2, "lutff_2/in_1"),
"ADDRESS_3": (25, 2, "lutff_3/in_1"),
"ADDRESS_4": (25, 2, "lutff_4/in_1"),
"ADDRESS_5": (25, 2, "lutff_5/in_1"),
"ADDRESS_6": (25, 2, "lutff_6/in_1"),
"ADDRESS_7": (25, 2, "lutff_7/in_1"),
"ADDRESS_8": (25, 2, "lutff_0/in_0"),
"ADDRESS_9": (25, 2, "lutff_1/in_0"),
"CHIPSELECT": (25, 3, "lutff_6/in_1"),
"CLOCK": (25, 1, "clk"),
"DATAIN_0": (25, 1, "lutff_0/in_3"),
"DATAIN_10": (25, 1, "lutff_2/in_1"),
"DATAIN_11": (25, 1, "lutff_3/in_1"),
"DATAIN_12": (25, 1, "lutff_4/in_1"),
"DATAIN_13": (25, 1, "lutff_5/in_1"),
"DATAIN_14": (25, 1, "lutff_6/in_1"),
"DATAIN_15": (25, 1, "lutff_7/in_1"),
"DATAIN_1": (25, 1, "lutff_1/in_3"),
"DATAIN_2": (25, 1, "lutff_2/in_3"),
"DATAIN_3": (25, 1, "lutff_3/in_3"),
"DATAIN_4": (25, 1, "lutff_4/in_3"),
"DATAIN_5": (25, 1, "lutff_5/in_3"),
"DATAIN_6": (25, 1, "lutff_6/in_3"),
"DATAIN_7": (25, 1, "lutff_7/in_3"),
"DATAIN_8": (25, 1, "lutff_0/in_1"),
"DATAIN_9": (25, 1, "lutff_1/in_1"),
"DATAOUT_0": (25, 1, "slf_op_0"),
"DATAOUT_10": (25, 2, "slf_op_2"),
"DATAOUT_11": (25, 2, "slf_op_3"),
"DATAOUT_12": (25, 2, "slf_op_4"),
"DATAOUT_13": (25, 2, "slf_op_5"),
"DATAOUT_14": (25, 2, "slf_op_6"),
"DATAOUT_15": (25, 2, "slf_op_7"),
"DATAOUT_1": (25, 1, "slf_op_1"),
"DATAOUT_2": (25, 1, "slf_op_2"),
"DATAOUT_3": (25, 1, "slf_op_3"),
"DATAOUT_4": (25, 1, "slf_op_4"),
"DATAOUT_5": (25, 1, "slf_op_5"),
"DATAOUT_6": (25, 1, "slf_op_6"),
"DATAOUT_7": (25, 1, "slf_op_7"),
"DATAOUT_8": (25, 2, "slf_op_0"),
"DATAOUT_9": (25, 2, "slf_op_1"),
"MASKWREN_0": (25, 3, "lutff_0/in_0"),
"MASKWREN_1": (25, 3, "lutff_1/in_0"),
"MASKWREN_2": (25, 3, "lutff_2/in_0"),
"MASKWREN_3": (25, 3, "lutff_3/in_0"),
"POWEROFF": (25, 4, "lutff_4/in_3"),
"SLEEP": (25, 4, "lutff_2/in_3"),
"SPRAM_EN": (25, 1, "CBIT_0"),
"STANDBY": (25, 4, "lutff_0/in_3"),
"WREN": (25, 3, "lutff_4/in_1"),
},
(25, 0, 4): {
"ADDRESS_0": (25, 2, "lutff_6/in_0"),
"ADDRESS_10": (25, 3, "lutff_0/in_1"),
"ADDRESS_11": (25, 3, "lutff_1/in_1"),
"ADDRESS_12": (25, 3, "lutff_2/in_1"),
"ADDRESS_13": (25, 3, "lutff_3/in_1"),
"ADDRESS_1": (25, 2, "lutff_7/in_0"),
"ADDRESS_2": (25, 3, "lutff_0/in_3"),
"ADDRESS_3": (25, 3, "lutff_1/in_3"),
"ADDRESS_4": (25, 3, "lutff_2/in_3"),
"ADDRESS_5": (25, 3, "lutff_3/in_3"),
"ADDRESS_6": (25, 3, "lutff_4/in_3"),
"ADDRESS_7": (25, 3, "lutff_5/in_3"),
"ADDRESS_8": (25, 3, "lutff_6/in_3"),
"ADDRESS_9": (25, 3, "lutff_7/in_3"),
"CHIPSELECT": (25, 3, "lutff_7/in_1"),
"CLOCK": (25, 2, "clk"),
"DATAIN_0": (25, 1, "lutff_0/in_0"),
"DATAIN_10": (25, 2, "lutff_2/in_3"),
"DATAIN_11": (25, 2, "lutff_3/in_3"),
"DATAIN_12": (25, 2, "lutff_4/in_3"),
"DATAIN_13": (25, 2, "lutff_5/in_3"),
"DATAIN_14": (25, 2, "lutff_6/in_3"),
"DATAIN_15": (25, 2, "lutff_7/in_3"),
"DATAIN_1": (25, 1, "lutff_1/in_0"),
"DATAIN_2": (25, 1, "lutff_2/in_0"),
"DATAIN_3": (25, 1, "lutff_3/in_0"),
"DATAIN_4": (25, 1, "lutff_4/in_0"),
"DATAIN_5": (25, 1, "lutff_5/in_0"),
"DATAIN_6": (25, 1, "lutff_6/in_0"),
"DATAIN_7": (25, 1, "lutff_7/in_0"),
"DATAIN_8": (25, 2, "lutff_0/in_3"),
"DATAIN_9": (25, 2, "lutff_1/in_3"),
"DATAOUT_0": (25, 3, "slf_op_0"),
"DATAOUT_10": (25, 4, "slf_op_2"),
"DATAOUT_11": (25, 4, "slf_op_3"),
"DATAOUT_12": (25, 4, "slf_op_4"),
"DATAOUT_13": (25, 4, "slf_op_5"),
"DATAOUT_14": (25, 4, "slf_op_6"),
"DATAOUT_15": (25, 4, "slf_op_7"),
"DATAOUT_1": (25, 3, "slf_op_1"),
"DATAOUT_2": (25, 3, "slf_op_2"),
"DATAOUT_3": (25, 3, "slf_op_3"),
"DATAOUT_4": (25, 3, "slf_op_4"),
"DATAOUT_5": (25, 3, "slf_op_5"),
"DATAOUT_6": (25, 3, "slf_op_6"),
"DATAOUT_7": (25, 3, "slf_op_7"),
"DATAOUT_8": (25, 4, "slf_op_0"),
"DATAOUT_9": (25, 4, "slf_op_1"),
"MASKWREN_0": (25, 3, "lutff_4/in_0"),
"MASKWREN_1": (25, 3, "lutff_5/in_0"),
"MASKWREN_2": (25, 3, "lutff_6/in_0"),
"MASKWREN_3": (25, 3, "lutff_7/in_0"),
"POWEROFF": (25, 4, "lutff_5/in_3"),
"SLEEP": (25, 4, "lutff_3/in_3"),
"SPRAM_EN": (25, 1, "CBIT_1"),
"STANDBY": (25, 4, "lutff_1/in_3"),
"WREN": (25, 3, "lutff_5/in_1"),
}
}
}
# This contains the data for extra cells not included
# in any previous databases
extra_cells_db = {
"5k" : {
("HFOSC", (0, 31, 1)) : {
"CLKHFPU": (0, 29, "lutff_0/in_1"),
"CLKHFEN": (0, 29, "lutff_7/in_3"),
"CLKHF": (0, 29, "glb_netwk_4"),
"CLKHF_FABRIC": (0, 28, "slf_op_7"),
"CLKHF_DIV_1": (0, 16, "CBIT_4"),
"CLKHF_DIV_0": (0, 16, "CBIT_3")
},
("LFOSC", (25, 31, 1)) : {
"CLKLFPU": (25, 29, "lutff_0/in_1"),
"CLKLFEN": (25, 29, "lutff_7/in_3"),
"CLKLF": (25, 29, "glb_netwk_5"),
"CLKLF_FABRIC": (25, 29, "slf_op_0")
},
("RGBA_DRV", (0, 30, 0)) : {
"CURREN": (25, 29, "lutff_6/in_3"),
"RGBLEDEN": (0, 30, "lutff_1/in_1"),
"RGB0PWM": (0, 30, "lutff_2/in_1"),
"RGB1PWM": (0, 30, "lutff_3/in_1"),
"RGB2PWM": (0, 30, "lutff_4/in_1"),
"RGBA_DRV_EN": (0, 28, "CBIT_5"),
"RGB0_CURRENT_0": (0, 28, "CBIT_6"),
"RGB0_CURRENT_1": (0, 28, "CBIT_7"),
"RGB0_CURRENT_2": (0, 29, "CBIT_0"),
"RGB0_CURRENT_3": (0, 29, "CBIT_1"),
"RGB0_CURRENT_4": (0, 29, "CBIT_2"),
"RGB0_CURRENT_5": (0, 29, "CBIT_3"),
"RGB1_CURRENT_0": (0, 29, "CBIT_4"),
"RGB1_CURRENT_1": (0, 29, "CBIT_5"),
"RGB1_CURRENT_2": (0, 29, "CBIT_6"),
"RGB1_CURRENT_3": (0, 29, "CBIT_7"),
"RGB1_CURRENT_4": (0, 30, "CBIT_0"),
"RGB1_CURRENT_5": (0, 30, "CBIT_1"),
"RGB2_CURRENT_0": (0, 30, "CBIT_2"),
"RGB2_CURRENT_1": (0, 30, "CBIT_3"),
"RGB2_CURRENT_2": (0, 30, "CBIT_4"),
"RGB2_CURRENT_3": (0, 30, "CBIT_5"),
"RGB2_CURRENT_4": (0, 30, "CBIT_6"),
"RGB2_CURRENT_5": (0, 30, "CBIT_7"),
"CURRENT_MODE": (0, 28, "CBIT_4"),
}
}
}
iotile_full_db = parse_db(iceboxdb.database_io_txt)
logictile_db = parse_db(iceboxdb.database_logic_txt, "1k")
logictile_5k_db = parse_db(iceboxdb.database_logic_txt, "5k")
@ -4179,6 +4744,26 @@ ramttile_5k_db = parse_db(iceboxdb.database_ramt_5k_txt, "5k")
rambtile_8k_db = parse_db(iceboxdb.database_ramb_8k_txt, "8k")
ramttile_8k_db = parse_db(iceboxdb.database_ramt_8k_txt, "8k")
ipcon_5k_db = parse_db(iceboxdb.database_ipcon_5k_txt, "5k")
dsp0_5k_db = parse_db(iceboxdb.database_dsp0_5k_txt, "5k")
dsp1_5k_db = parse_db(iceboxdb.database_dsp1_5k_txt, "5k")
#This bit doesn't exist in DB because icecube won't ever set it,
#but it exists
dsp1_5k_db.append([["B4[7]"], "IpConfig", "CBIT_5"])
dsp2_5k_db = parse_db(iceboxdb.database_dsp2_5k_txt, "5k")
dsp3_5k_db = parse_db(iceboxdb.database_dsp3_5k_txt, "5k")
#Add missing LC_ bits to DSP and IPCon databases
for db_to_fix in [ipcon_5k_db, dsp0_5k_db, dsp1_5k_db, dsp2_5k_db, dsp3_5k_db]:
for entry in db_to_fix:
if len(entry) >= 2 and entry[1].startswith("LC_"):
for lentry in logictile_5k_db:
if len(lentry) >= 2 and lentry[1] == entry[1]:
entry[0] = lentry[0]
iotile_l_db = list()
iotile_r_db = list()
iotile_t_db = list()
@ -4223,16 +4808,28 @@ logictile_384_db.append([["B1[50]"], "CarryInSet"])
iotile_t_5k_db = list(iotile_t_db)
iotile_t_5k_db.append([["B14[15]"], "IoCtrl", "padeb_test_1"])
iotile_t_5k_db.append([["B15[14]"], "IoCtrl", "padeb_test_0"])
iotile_t_5k_db.append([["B7[10]"], "IoCtrl", "cf_bit_32"])
iotile_t_5k_db.append([["B6[10]"], "IoCtrl", "cf_bit_33"])
iotile_t_5k_db.append([["B7[15]"], "IoCtrl", "cf_bit_34"])
iotile_t_5k_db.append([["B6[15]"], "IoCtrl", "cf_bit_35"])
iotile_t_5k_db.append([["B13[10]"], "IoCtrl", "cf_bit_36"])
iotile_t_5k_db.append([["B12[10]"], "IoCtrl", "cf_bit_37"])
iotile_t_5k_db.append([["B13[15]"], "IoCtrl", "cf_bit_38"])
iotile_t_5k_db.append([["B12[15]"], "IoCtrl", "cf_bit_39"])
iotile_b_5k_db = list(iotile_b_db)
iotile_b_5k_db.append([["B14[15]"], "IoCtrl", "padeb_test_1"])
iotile_b_5k_db.append([["B15[14]"], "IoCtrl", "padeb_test_0"])
iotile_b_5k_db.append([["B7[10]"], "IoCtrl", "cf_bit_32"])
iotile_b_5k_db.append([["B6[10]"], "IoCtrl", "cf_bit_33"])
iotile_b_5k_db.append([["B7[15]"], "IoCtrl", "cf_bit_34"])
iotile_b_5k_db.append([["B6[15]"], "IoCtrl", "cf_bit_35"])
iotile_b_5k_db.append([["B13[10]"], "IoCtrl", "cf_bit_36"])
iotile_b_5k_db.append([["B12[10]"], "IoCtrl", "cf_bit_37"])
iotile_b_5k_db.append([["B13[15]"], "IoCtrl", "cf_bit_38"])
iotile_b_5k_db.append([["B12[15]"], "IoCtrl", "cf_bit_39"])
for db in [iotile_l_db, iotile_r_db, iotile_t_db, iotile_b_db, iotile_t_5k_db, iotile_b_5k_db, logictile_db, logictile_5k_db, logictile_8k_db, logictile_384_db, rambtile_db, ramttile_db, rambtile_5k_db, ramttile_5k_db, rambtile_8k_db, ramttile_8k_db]:
for db in [iotile_l_db, iotile_r_db, iotile_t_db, iotile_b_db, iotile_t_5k_db, iotile_b_5k_db, logictile_db, logictile_5k_db, logictile_8k_db, logictile_384_db, rambtile_db, ramttile_db, rambtile_5k_db, ramttile_5k_db, rambtile_8k_db, ramttile_8k_db, dsp0_5k_db, dsp1_5k_db, dsp2_5k_db, dsp3_5k_db, ipcon_5k_db]:
for entry in db:
if entry[1] in ("buffer", "routing"):
entry[2] = netname_normalize(entry[2],

View File

@ -129,7 +129,8 @@ print("""#
# .logic_tile X Y
# .ramb_tile X Y
# .ramt_tile X Y
#
# .dsp[0..3]_tile X Y
# .ipcon_tile X Y
# declares the existence of a IO/LOGIC/RAM tile with the given coordinates
#
#
@ -137,6 +138,8 @@ print("""#
# .logic_tile_bits COLUMNS ROWS
# .ramb_tile_bits COLUMNS ROWS
# .ramt_tile_bits COLUMNS ROWS
# .dsp[0..3]_tile_bits X Y
# .ipcon_tile_bits X Y
# FUNCTION_1 CONFIG_BITS_NAMES_1
# FUNCTION_2 CONFIG_BITS_NAMES_2
# ...
@ -145,6 +148,7 @@ print("""#
#
#
# .extra_cell X Y <cell-type>
# .extra_cell X Y Z <cell-type>
# KEY MULTI-FIELD-VALUE
# ....
#
@ -238,6 +242,16 @@ for idx in sorted(ic.ramt_tiles):
print(".ramt_tile %d %d" % idx)
print()
for dsp_idx in range(4):
for idx in sorted(ic.dsp_tiles[dsp_idx]):
x, y = idx
print(".dsp%d_tile %d %d" % (dsp_idx, x, y))
print()
for idx in sorted(ic.ipcon_tiles):
print(".ipcon_tile %d %d" % idx)
print()
def print_tile_nonrouting_bits(tile_type, idx):
tx = idx[0]
ty = idx[1]
@ -266,6 +280,11 @@ if not mode_384:
print_tile_nonrouting_bits("ramb", list(ic.ramb_tiles.keys())[0])
print_tile_nonrouting_bits("ramt", list(ic.ramt_tiles.keys())[0])
if ic.is_ultra():
for dsp_idx in range(4):
print_tile_nonrouting_bits("dsp%d" % dsp_idx, list(ic.dsp_tiles[dsp_idx].keys())[0])
print_tile_nonrouting_bits("ipcon", list(ic.ipcon_tiles.keys())[0])
print(".extra_cell 0 0 WARMBOOT")
for key in sorted(icebox.warmbootinfo_db[ic.device]):
print("%s %s" % (key, " ".join([str(k) for k in icebox.warmbootinfo_db[ic.device][key]])))
@ -285,6 +304,38 @@ for pllid in ic.pll_list():
print("%s %s" % (key, " ".join([str(k) for k in pllinfo[key]])))
print()
for dsploc in ic.dsp_tiles[0]:
x, y = dsploc
print(".extra_cell %d %d 0 MAC16" % dsploc)
nets = ic.get_dsp_nets_db(x, y)
for key in sorted(nets):
print("%s %s" % (key, " ".join([str(k) for k in nets[key]])))
cfg = ic.get_dsp_config_db(x, y)
for key in sorted(cfg):
print("%s %s" % (key, " ".join([str(k) for k in cfg[key]])))
print()
if ic.device in icebox.extra_cells_db:
for cell in icebox.extra_cells_db[ic.device]:
name, loc = cell
x, y, z = loc
print(".extra_cell %d %d %d %s" % (x, y, z, name))
cellinfo = icebox.extra_cells_db[ic.device][cell]
for key in sorted(cellinfo):
print("%s %s" % (key, " ".join([str(k) for k in cellinfo[key]])))
print()
if ic.device in icebox.spram_db:
for cell in icebox.spram_db[ic.device]:
loc = cell
x, y, z = loc
print(".extra_cell %d %d %d SPRAM" % (x, y, z))
cellinfo = icebox.spram_db[ic.device][cell]
for key in sorted(cellinfo):
print("%s %s" % (key, " ".join([str(k) for k in cellinfo[key]])))
print()
print(".extra_bits")
extra_bits = dict()
for idx in sorted(ic.extra_bits_db()):

View File

@ -117,7 +117,7 @@ def print_tile(stmt, ic, x, y, tile, db):
bitinfo.append("")
extra_text = ""
for i in range(len(line)):
if 36 <= i <= 45 and re.search(r"logic_tile", stmt):
if 36 <= i <= 45 and re.search(r"(logic_tile|dsp\d_tile|ipcon_tile)", stmt):
lutff_idx = k // 2
lutff_bitnum = (i-36) + 10*(k%2)
if line[i] == "1":
@ -166,6 +166,13 @@ for idx in ic.ramb_tiles:
for idx in ic.ramt_tiles:
print_tile(".ramt_tile %d %d" % idx, ic, idx[0], idx[1], ic.ramt_tiles[idx], ic.tile_db(idx[0], idx[1]))
for i in range(4):
for idx in ic.dsp_tiles[i]:
print_tile(".dsp%d_tile %d %d" % (i, idx[0], idx[1]), ic, idx[0], idx[1], ic.dsp_tiles[i][idx], ic.tile_db(idx[0], idx[1]))
for idx in ic.ipcon_tiles:
print_tile(".ipcon_tile %d %d" % idx, ic, idx[0], idx[1], ic.ipcon_tiles[idx], ic.tile_db(idx[0], idx[1]))
for bit in ic.extra_bits:
print()
print(".extra_bit %d %d %d" % bit)

View File

@ -136,6 +136,7 @@ text_wires = list()
text_ports = list()
luts_queue = set()
special_5k_queue = set()
text_func = list()
failed_drivers_check = list()
@ -160,6 +161,7 @@ def is_interconn(netname):
if netname.startswith("span12_"): return True
if netname.startswith("logic_op_"): return True
if netname.startswith("neigh_op_"): return True
if netname.startswith("slf_op_"): return True
if netname.startswith("local_"): return True
return False
@ -315,7 +317,11 @@ for segs in sorted(ic.group_segments(extra_connections=extra_connections, extra_
match = re.match("lutff_(\d+)/", s[2])
if match:
luts_queue.add((s[0], s[1], int(match.group(1))))
#IpCon and DSP tiles look like logic tiles, but aren't.
if ic.device == "5k" and (s[0] == 0 or s[0] == ic.max_x):
special_5k_queue.add((s[0], s[1]))
else:
luts_queue.add((s[0], s[1], int(match.group(1))))
nets[n] = segs
@ -752,6 +758,28 @@ for tile in ic.ramb_tiles:
text_func.append(");")
text_func.append("")
for i in range(4):
for tile in ic.dsp_tiles[i]:
if tile in special_5k_queue:
#TODO: print config
x = tile[0]
y = tile[1]
net_clk = seg_to_net((x, y, "lutff_global/clk"), "1'b0")
net_sr = seg_to_net((x, y, "lutff_global/s_r"), "1'b0")
#TEMP: for tracing only
text_func.append("/* DSP%d %2d %2d */ assign dsp%d_%d_%d_clk = %s;" % (i, x, y, i, x, y, net_clk))
text_func.append("/* DSP%d %2d %2d */ assign dsp%d_%d_%d_sr = %s;" % (i, x, y, i, x, y, net_sr))
for j in range(8):
net_in0 = seg_to_net((x, y, "lutff_%d/in_0" % j), "1'b0")
net_in1 = seg_to_net((x, y, "lutff_%d/in_1" % j), "1'b0")
net_in2 = seg_to_net((x, y, "lutff_%d/in_2" % j), "1'b0")
net_in3 = seg_to_net((x, y, "lutff_%d/in_3" % j), "1'b0")
#TODO: cin, cout
text_func.append("/* DSP%d %2d %2d %d*/ assign dsp%d_%d_%d_in_%d_0 = %s;" % (i, x, y, j, i, x, y, j, net_in0))
text_func.append("/* DSP%d %2d %2d %d*/ assign dsp%d_%d_%d_in_%d_1 = %s;" % (i, x, y, j, i, x, y, j, net_in1))
text_func.append("/* DSP%d %2d %2d %d*/ assign dsp%d_%d_%d_in_%d_2 = %s;" % (i, x, y, j, i, x, y, j, net_in2))
text_func.append("/* DSP%d %2d %2d %d*/ assign dsp%d_%d_%d_in_%d_3 = %s;" % (i, x, y, j, i, x, y, j, net_in3))
wire_to_reg = set()
lut_assigns = list()
const_assigns = list()

File diff suppressed because it is too large Load Diff

View File

@ -42,8 +42,11 @@ ifneq ($(DEVICECLASS),384)
TESTS += pll
TESTS += aig
endif
database: bitdata_io.txt bitdata_logic.txt bitdata_ramb$(RAM_SUFFIX).txt bitdata_ramt$(RAM_SUFFIX).txt
ifeq ($(DEVICECLASS),5k)
TESTS += dsp
TESTS += upip
endif
database: bitdata_io.txt bitdata_logic.txt bitdata_ramb$(RAM_SUFFIX).txt bitdata_ramt$(RAM_SUFFIX).txt bitdata_dsp0_5k.txt bitdata_dsp1_5k.txt bitdata_dsp2_5k.txt bitdata_dsp3_5k.txt bitdata_ipcon_5k.txt
ifneq ($(RAM_SUFFIX),)
cp cached_ramb.txt bitdata_ramb.txt
cp cached_ramt.txt bitdata_ramt.txt
@ -55,6 +58,12 @@ endif
ifneq ($(RAM_SUFFIX),_5k)
cp cached_ramb_5k.txt bitdata_ramb_5k.txt
cp cached_ramt_5k.txt bitdata_ramt_5k.txt
cp cached_dsp0_5k.txt bitdata_dsp0_5k.txt
cp cached_dsp1_5k.txt bitdata_dsp1_5k.txt
cp cached_dsp2_5k.txt bitdata_dsp2_5k.txt
cp cached_dsp3_5k.txt bitdata_dsp3_5k.txt
cp cached_ipcon_5k.txt bitdata_ipcon_5k.txt
endif
ICEDEVICE=$(DEVICECLASS) python3 database.py
python3 export.py
@ -62,6 +71,11 @@ endif
diff -U0 cached_logic.txt bitdata_logic.txt || cp -v bitdata_logic.txt cached_logic.txt
diff -U0 cached_ramb$(RAM_SUFFIX).txt bitdata_ramb$(RAM_SUFFIX).txt || cp -v bitdata_ramb$(RAM_SUFFIX).txt cached_ramb$(RAM_SUFFIX).txt
diff -U0 cached_ramt$(RAM_SUFFIX).txt bitdata_ramt$(RAM_SUFFIX).txt || cp -v bitdata_ramt$(RAM_SUFFIX).txt cached_ramt$(RAM_SUFFIX).txt
diff -U0 cached_dsp0_5k.txt bitdata_dsp0_5k.txt || cp -v bitdata_dsp0_5k.txt cached_dsp0_5k.txt
diff -U0 cached_dsp1_5k.txt bitdata_dsp1_5k.txt || cp -v bitdata_dsp1_5k.txt cached_dsp1_5k.txt
diff -U0 cached_dsp2_5k.txt bitdata_dsp2_5k.txt || cp -v bitdata_dsp2_5k.txt cached_dsp2_5k.txt
diff -U0 cached_dsp3_5k.txt bitdata_dsp3_5k.txt || cp -v bitdata_dsp3_5k.txt cached_dsp3_5k.txt
diff -U0 cached_ipcon_5k.txt bitdata_ipcon_5k.txt || cp -v bitdata_ipcon_5k.txt cached_ipcon_5k.txt
timings:
ifeq ($(DEVICECLASS),8k)
@ -97,11 +111,18 @@ timings_html:
python3 timings.py -h tmedges.txt -t timings_lp8k.txt -l "LP8K with default temp/volt settings" > timings_lp8k.html
python3 timings.py -h tmedges.txt -t timings_lp384.txt -l "LP384 with default temp/volt settings" > timings_lp384.html
data_cached.txt: cached_io.txt cached_logic.txt cached_ramb$(RAM_SUFFIX).txt cached_ramt$(RAM_SUFFIX).txt
data_cached.txt: cached_io.txt cached_logic.txt cached_ramb$(RAM_SUFFIX).txt cached_ramt$(RAM_SUFFIX).txt cached_dsp0_5k.txt cached_dsp1_5k.txt cached_dsp2_5k.txt cached_dsp3_5k.txt cached_ipcon_5k.txt
gawk '{ print "io", $$0; }' cached_io.txt > data_cached.new
gawk '{ print "logic", $$0; }' cached_logic.txt >> data_cached.new
gawk '{ print "ramb$(RAM_SUFFIX)", $$0; }' cached_ramb$(RAM_SUFFIX).txt >> data_cached.new
gawk '{ print "ramt$(RAM_SUFFIX)", $$0; }' cached_ramt$(RAM_SUFFIX).txt >> data_cached.new
gawk '{ print "dsp0_5k", $$0; }' cached_dsp0_5k.txt >> data_cached.new
gawk '{ print "dsp1_5k", $$0; }' cached_dsp1_5k.txt >> data_cached.new
gawk '{ print "dsp2_5k", $$0; }' cached_dsp2_5k.txt >> data_cached.new
gawk '{ print "dsp3_5k", $$0; }' cached_dsp3_5k.txt >> data_cached.new
gawk '{ print "ipcon_5k", $$0; }' cached_ipcon_5k.txt >> data_cached.new
mv data_cached.new data_cached.txt
bitdata_io.txt: data_cached.txt $(addprefix data_$(DEVICECLASS)_,$(addsuffix .txt,$(TESTS)))
@ -116,6 +137,21 @@ bitdata_ramb$(RAM_SUFFIX).txt: data_cached.txt $(addprefix data_$(DEVICECLASS)_,
bitdata_ramt$(RAM_SUFFIX).txt: data_cached.txt $(addprefix data_$(DEVICECLASS)_,$(addsuffix .txt,$(TESTS)))
grep ^ramt$(RAM_SUFFIX) $^ | tr -s ' ' | tr -d '\r' | cut -f2- -d' ' | sort -u > $@
bitdata_dsp0_5k.txt: data_cached.txt $(addprefix data_$(DEVICECLASS)_,$(addsuffix .txt,$(TESTS)))
grep ^dsp0_5k $^ | tr -s ' ' | tr -d '\r' | cut -f2- -d' ' | sort -u > $@
bitdata_dsp1_5k.txt: data_cached.txt $(addprefix data_$(DEVICECLASS)_,$(addsuffix .txt,$(TESTS)))
grep ^dsp1_5k $^ | tr -s ' ' | tr -d '\r' | cut -f2- -d' ' | sort -u > $@
bitdata_dsp2_5k.txt: data_cached.txt $(addprefix data_$(DEVICECLASS)_,$(addsuffix .txt,$(TESTS)))
grep ^dsp2_5k $^ | tr -s ' ' | tr -d '\r' | cut -f2- -d' ' | sort -u > $@
bitdata_dsp3_5k.txt: data_cached.txt $(addprefix data_$(DEVICECLASS)_,$(addsuffix .txt,$(TESTS)))
grep ^dsp3_5k $^ | tr -s ' ' | tr -d '\r' | cut -f2- -d' ' | sort -u > $@
bitdata_ipcon_5k.txt: data_cached.txt $(addprefix data_$(DEVICECLASS)_,$(addsuffix .txt,$(TESTS)))
grep ^ipcon_5k $^ | tr -s ' ' | tr -d '\r' | cut -f2- -d' ' | sort -u > $@
datafiles: $(addprefix data_,$(addsuffix .txt,$(TESTS)))
../icepack/icepack:

3272
icefuzz/cached_dsp0_5k.txt Normal file

File diff suppressed because it is too large Load Diff

3033
icefuzz/cached_dsp1_5k.txt Normal file

File diff suppressed because it is too large Load Diff

3057
icefuzz/cached_dsp2_5k.txt Normal file

File diff suppressed because it is too large Load Diff

3164
icefuzz/cached_dsp3_5k.txt Normal file

File diff suppressed because it is too large Load Diff

3471
icefuzz/cached_ipcon_5k.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
(0 0) Negative Clock bit
(0 10) routing glb_netwk_2 <X> glb2local_2
(0 10) routing glb_netwk_3 <X> glb2local_2
(0 10) routing glb_netwk_6 <X> glb2local_2
(0 10) routing glb_netwk_7 <X> glb2local_2
@ -6,11 +7,14 @@
(0 11) routing glb_netwk_3 <X> glb2local_2
(0 11) routing glb_netwk_5 <X> glb2local_2
(0 11) routing glb_netwk_7 <X> glb2local_2
(0 12) routing glb_netwk_2 <X> glb2local_3
(0 12) routing glb_netwk_3 <X> glb2local_3
(0 12) routing glb_netwk_6 <X> glb2local_3
(0 12) routing glb_netwk_7 <X> glb2local_3
(0 13) routing glb_netwk_1 <X> glb2local_3
(0 13) routing glb_netwk_3 <X> glb2local_3
(0 13) routing glb_netwk_5 <X> glb2local_3
(0 13) routing glb_netwk_7 <X> glb2local_3
(0 14) routing glb_netwk_4 <X> wire_bram/ram/RE
(0 14) routing glb_netwk_6 <X> wire_bram/ram/RE
(0 14) routing lc_trk_g2_4 <X> wire_bram/ram/RE
@ -31,7 +35,6 @@
(0 3) routing glb_netwk_7 <X> wire_bram/ram/RCLK
(0 3) routing lc_trk_g1_1 <X> wire_bram/ram/RCLK
(0 3) routing lc_trk_g3_1 <X> wire_bram/ram/RCLK
(0 4) routing glb_netwk_5 <X> wire_bram/ram/RCLKE
(0 4) routing lc_trk_g2_2 <X> wire_bram/ram/RCLKE
(0 4) routing lc_trk_g3_3 <X> wire_bram/ram/RCLKE
(0 5) routing lc_trk_g1_3 <X> wire_bram/ram/RCLKE
@ -45,12 +48,11 @@
(0 7) routing glb_netwk_7 <X> glb2local_0
(0 8) routing glb_netwk_3 <X> glb2local_1
(0 8) routing glb_netwk_6 <X> glb2local_1
(0 8) routing glb_netwk_7 <X> glb2local_1
(0 9) routing glb_netwk_1 <X> glb2local_1
(0 9) routing glb_netwk_3 <X> glb2local_1
(0 9) routing glb_netwk_5 <X> glb2local_1
(0 9) routing glb_netwk_7 <X> glb2local_1
(1 10) Enable bit of Mux _local_links/global_mux_2 => glb_netwk_1 glb2local_2
(1 10) Enable bit of Mux _local_links/global_mux_2 => glb_netwk_2 glb2local_2
(1 10) Enable bit of Mux _local_links/global_mux_2 => glb_netwk_3 glb2local_2
(1 10) Enable bit of Mux _local_links/global_mux_2 => glb_netwk_4 glb2local_2
(1 10) Enable bit of Mux _local_links/global_mux_2 => glb_netwk_5 glb2local_2
@ -61,13 +63,16 @@
(1 11) routing glb_netwk_6 <X> glb2local_2
(1 11) routing glb_netwk_7 <X> glb2local_2
(1 12) Enable bit of Mux _local_links/global_mux_3 => glb_netwk_1 glb2local_3
(1 12) Enable bit of Mux _local_links/global_mux_3 => glb_netwk_2 glb2local_3
(1 12) Enable bit of Mux _local_links/global_mux_3 => glb_netwk_3 glb2local_3
(1 12) Enable bit of Mux _local_links/global_mux_3 => glb_netwk_4 glb2local_3
(1 12) Enable bit of Mux _local_links/global_mux_3 => glb_netwk_5 glb2local_3
(1 12) Enable bit of Mux _local_links/global_mux_3 => glb_netwk_6 glb2local_3
(1 12) Enable bit of Mux _local_links/global_mux_3 => glb_netwk_7 glb2local_3
(1 13) routing glb_netwk_4 <X> glb2local_3
(1 13) routing glb_netwk_5 <X> glb2local_3
(1 13) routing glb_netwk_6 <X> glb2local_3
(1 13) routing glb_netwk_7 <X> glb2local_3
(1 14) Enable bit of Mux _global_links/set_rst_mux => glb_netwk_2 wire_bram/ram/RE
(1 14) Enable bit of Mux _global_links/set_rst_mux => glb_netwk_4 wire_bram/ram/RE
(1 14) Enable bit of Mux _global_links/set_rst_mux => glb_netwk_6 wire_bram/ram/RE
@ -84,7 +89,6 @@
(1 2) routing glb_netwk_6 <X> wire_bram/ram/RCLK
(1 2) routing glb_netwk_7 <X> wire_bram/ram/RCLK
(1 3) Enable bit of Mux _span_links/cross_mux_horz_5 => sp12_h_l_9 sp4_h_r_17
(1 4) Enable bit of Mux _global_links/ce_mux => glb_netwk_5 wire_bram/ram/RCLKE
(1 4) Enable bit of Mux _global_links/ce_mux => lc_trk_g0_2 wire_bram/ram/RCLKE
(1 4) Enable bit of Mux _global_links/ce_mux => lc_trk_g1_3 wire_bram/ram/RCLKE
(1 4) Enable bit of Mux _global_links/ce_mux => lc_trk_g2_2 wire_bram/ram/RCLKE
@ -108,11 +112,9 @@
(1 8) Enable bit of Mux _local_links/global_mux_1 => glb_netwk_4 glb2local_1
(1 8) Enable bit of Mux _local_links/global_mux_1 => glb_netwk_5 glb2local_1
(1 8) Enable bit of Mux _local_links/global_mux_1 => glb_netwk_6 glb2local_1
(1 8) Enable bit of Mux _local_links/global_mux_1 => glb_netwk_7 glb2local_1
(1 9) routing glb_netwk_4 <X> glb2local_1
(1 9) routing glb_netwk_5 <X> glb2local_1
(1 9) routing glb_netwk_6 <X> glb2local_1
(1 9) routing glb_netwk_7 <X> glb2local_1
(10 0) routing sp4_h_l_40 <X> sp4_h_r_1
(10 0) routing sp4_h_l_47 <X> sp4_h_r_1
(10 0) routing sp4_v_b_7 <X> sp4_h_r_1
@ -214,6 +216,7 @@
(11 2) routing sp4_v_b_11 <X> sp4_v_t_39
(11 2) routing sp4_v_b_6 <X> sp4_v_t_39
(11 3) routing sp4_h_r_2 <X> sp4_h_l_39
(11 3) routing sp4_h_r_6 <X> sp4_h_l_39
(11 3) routing sp4_v_t_39 <X> sp4_h_l_39
(11 3) routing sp4_v_t_45 <X> sp4_h_l_39
(11 4) routing sp4_h_l_46 <X> sp4_v_b_5
@ -264,6 +267,7 @@
(12 13) routing sp4_h_l_46 <X> sp4_v_b_11
(12 13) routing sp4_h_r_11 <X> sp4_v_b_11
(12 13) routing sp4_v_t_45 <X> sp4_v_b_11
(12 14) routing sp4_h_r_8 <X> sp4_h_l_46
(12 14) routing sp4_v_b_11 <X> sp4_h_l_46
(12 14) routing sp4_v_t_40 <X> sp4_h_l_46
(12 14) routing sp4_v_t_46 <X> sp4_h_l_46
@ -332,6 +336,7 @@
(13 14) routing sp4_v_b_11 <X> sp4_v_t_46
(13 14) routing sp4_v_b_3 <X> sp4_v_t_46
(13 15) routing sp4_h_r_3 <X> sp4_h_l_46
(13 15) routing sp4_h_r_8 <X> sp4_h_l_46
(13 15) routing sp4_v_b_6 <X> sp4_h_l_46
(13 15) routing sp4_v_t_40 <X> sp4_h_l_46
(13 2) routing sp4_h_r_2 <X> sp4_v_t_39
@ -339,6 +344,7 @@
(13 2) routing sp4_v_b_2 <X> sp4_v_t_39
(13 2) routing sp4_v_b_6 <X> sp4_v_t_39
(13 3) routing sp4_h_r_11 <X> sp4_h_l_39
(13 3) routing sp4_h_r_6 <X> sp4_h_l_39
(13 3) routing sp4_v_b_9 <X> sp4_h_l_39
(13 3) routing sp4_v_t_45 <X> sp4_h_l_39
(13 4) routing sp4_h_l_40 <X> sp4_v_b_5
@ -1089,7 +1095,6 @@
(2 10) Enable bit of Mux _span_links/cross_mux_horz_9 => sp12_h_l_17 sp4_h_r_21
(2 12) Enable bit of Mux _span_links/cross_mux_horz_10 => sp12_h_r_20 sp4_h_l_11
(2 14) Enable bit of Mux _span_links/cross_mux_horz_11 => sp12_h_r_22 sp4_h_r_23
(2 2) Enable bit of Mux _global_links/clk_mux => glb_netwk_0 wire_bram/ram/RCLK
(2 2) Enable bit of Mux _global_links/clk_mux => glb_netwk_1 wire_bram/ram/RCLK
(2 2) Enable bit of Mux _global_links/clk_mux => glb_netwk_2 wire_bram/ram/RCLK
(2 2) Enable bit of Mux _global_links/clk_mux => glb_netwk_3 wire_bram/ram/RCLK
@ -3428,7 +3433,6 @@
(7 14) Column buffer control bit: MEMB_colbuf_cntl_7
(7 15) Column buffer control bit: MEMB_colbuf_cntl_6
(7 8) Column buffer control bit: MEMB_colbuf_cntl_1
(7 9) Column buffer control bit: MEMB_colbuf_cntl_0
(8 0) routing sp4_h_l_36 <X> sp4_h_r_1
(8 0) routing sp4_h_l_40 <X> sp4_h_r_1
(8 0) routing sp4_v_b_1 <X> sp4_h_r_1

View File

@ -17,6 +17,7 @@
(0 14) routing glb_netwk_6 <X> wire_bram/ram/WE
(0 14) routing lc_trk_g2_4 <X> wire_bram/ram/WE
(0 14) routing lc_trk_g3_5 <X> wire_bram/ram/WE
(0 15) routing glb_netwk_2 <X> wire_bram/ram/WE
(0 15) routing glb_netwk_6 <X> wire_bram/ram/WE
(0 15) routing lc_trk_g1_5 <X> wire_bram/ram/WE
(0 15) routing lc_trk_g3_5 <X> wire_bram/ram/WE
@ -32,10 +33,8 @@
(0 3) routing glb_netwk_7 <X> wire_bram/ram/WCLK
(0 3) routing lc_trk_g1_1 <X> wire_bram/ram/WCLK
(0 3) routing lc_trk_g3_1 <X> wire_bram/ram/WCLK
(0 4) routing glb_netwk_5 <X> wire_bram/ram/WCLKE
(0 4) routing lc_trk_g2_2 <X> wire_bram/ram/WCLKE
(0 4) routing lc_trk_g3_3 <X> wire_bram/ram/WCLKE
(0 5) routing glb_netwk_3 <X> wire_bram/ram/WCLKE
(0 5) routing lc_trk_g1_3 <X> wire_bram/ram/WCLKE
(0 5) routing lc_trk_g3_3 <X> wire_bram/ram/WCLKE
(0 6) routing glb_netwk_3 <X> glb2local_0
@ -70,6 +69,7 @@
(1 13) routing glb_netwk_5 <X> glb2local_3
(1 13) routing glb_netwk_6 <X> glb2local_3
(1 13) routing glb_netwk_7 <X> glb2local_3
(1 14) Enable bit of Mux _global_links/set_rst_mux => glb_netwk_2 wire_bram/ram/WE
(1 14) Enable bit of Mux _global_links/set_rst_mux => glb_netwk_4 wire_bram/ram/WE
(1 14) Enable bit of Mux _global_links/set_rst_mux => glb_netwk_6 wire_bram/ram/WE
(1 14) Enable bit of Mux _global_links/set_rst_mux => lc_trk_g0_4 wire_bram/ram/WE
@ -85,8 +85,6 @@
(1 2) routing glb_netwk_6 <X> wire_bram/ram/WCLK
(1 2) routing glb_netwk_7 <X> wire_bram/ram/WCLK
(1 3) Enable bit of Mux _span_links/cross_mux_horz_5 => sp12_h_r_10 sp4_h_r_17
(1 4) Enable bit of Mux _global_links/ce_mux => glb_netwk_3 wire_bram/ram/WCLKE
(1 4) Enable bit of Mux _global_links/ce_mux => glb_netwk_5 wire_bram/ram/WCLKE
(1 4) Enable bit of Mux _global_links/ce_mux => lc_trk_g0_2 wire_bram/ram/WCLKE
(1 4) Enable bit of Mux _global_links/ce_mux => lc_trk_g1_3 wire_bram/ram/WCLKE
(1 4) Enable bit of Mux _global_links/ce_mux => lc_trk_g2_2 wire_bram/ram/WCLKE
@ -181,6 +179,7 @@
(11 0) routing sp4_h_r_9 <X> sp4_v_b_2
(11 0) routing sp4_v_t_43 <X> sp4_v_b_2
(11 0) routing sp4_v_t_46 <X> sp4_v_b_2
(11 1) routing sp4_h_l_39 <X> sp4_h_r_2
(11 1) routing sp4_h_l_43 <X> sp4_h_r_2
(11 1) routing sp4_v_b_2 <X> sp4_h_r_2
(11 1) routing sp4_v_b_8 <X> sp4_h_r_2
@ -221,6 +220,7 @@
(11 4) routing sp4_v_t_39 <X> sp4_v_b_5
(11 4) routing sp4_v_t_44 <X> sp4_v_b_5
(11 5) routing sp4_h_l_40 <X> sp4_h_r_5
(11 5) routing sp4_h_l_44 <X> sp4_h_r_5
(11 5) routing sp4_v_b_11 <X> sp4_h_r_5
(11 5) routing sp4_v_b_5 <X> sp4_h_r_5
(11 6) routing sp4_h_l_37 <X> sp4_v_t_40
@ -348,6 +348,7 @@
(13 4) routing sp4_v_t_40 <X> sp4_v_b_5
(13 4) routing sp4_v_t_44 <X> sp4_v_b_5
(13 5) routing sp4_h_l_39 <X> sp4_h_r_5
(13 5) routing sp4_h_l_44 <X> sp4_h_r_5
(13 5) routing sp4_v_b_11 <X> sp4_h_r_5
(13 5) routing sp4_v_t_37 <X> sp4_h_r_5
(13 6) routing sp4_h_r_11 <X> sp4_v_t_40
@ -439,7 +440,6 @@
(14 3) routing sp4_h_r_4 <X> lc_trk_g0_4
(14 3) routing sp4_r_v_b_28 <X> lc_trk_g0_4
(14 3) routing sp4_v_t_1 <X> lc_trk_g0_4
(14 3) routing top_op_4 <X> lc_trk_g0_4
(14 4) routing bnr_op_0 <X> lc_trk_g1_0
(14 4) routing lft_op_0 <X> lc_trk_g1_0
(14 4) routing sp12_h_r_0 <X> lc_trk_g1_0
@ -555,7 +555,6 @@
(15 3) routing sp4_h_r_20 <X> lc_trk_g0_4
(15 3) routing sp4_h_r_4 <X> lc_trk_g0_4
(15 3) routing sp4_v_b_20 <X> lc_trk_g0_4
(15 3) routing top_op_4 <X> lc_trk_g0_4
(15 4) routing lft_op_1 <X> lc_trk_g1_1
(15 4) routing sp12_h_r_1 <X> lc_trk_g1_1
(15 4) routing sp4_h_r_1 <X> lc_trk_g1_1
@ -866,7 +865,6 @@
(17 3) Enable bit of Mux _local_links/g0_mux_4 => sp4_v_b_20 lc_trk_g0_4
(17 3) Enable bit of Mux _local_links/g0_mux_4 => sp4_v_b_4 lc_trk_g0_4
(17 3) Enable bit of Mux _local_links/g0_mux_4 => sp4_v_t_1 lc_trk_g0_4
(17 3) Enable bit of Mux _local_links/g0_mux_4 => top_op_4 lc_trk_g0_4
(17 4) Enable bit of Mux _local_links/g1_mux_1 => bnr_op_1 lc_trk_g1_1
(17 4) Enable bit of Mux _local_links/g1_mux_1 => lft_op_1 lc_trk_g1_1
(17 4) Enable bit of Mux _local_links/g1_mux_1 => sp12_h_l_6 lc_trk_g1_1
@ -1085,7 +1083,6 @@
(2 10) Enable bit of Mux _span_links/cross_mux_horz_9 => sp12_h_r_18 sp4_h_l_8
(2 12) Enable bit of Mux _span_links/cross_mux_horz_10 => sp12_h_r_20 sp4_h_r_22
(2 14) Enable bit of Mux _span_links/cross_mux_horz_11 => sp12_h_l_21 sp4_h_l_10
(2 2) Enable bit of Mux _global_links/clk_mux => glb_netwk_0 wire_bram/ram/WCLK
(2 2) Enable bit of Mux _global_links/clk_mux => glb_netwk_1 wire_bram/ram/WCLK
(2 2) Enable bit of Mux _global_links/clk_mux => glb_netwk_2 wire_bram/ram/WCLK
(2 2) Enable bit of Mux _global_links/clk_mux => glb_netwk_3 wire_bram/ram/WCLK
@ -3433,7 +3430,6 @@
(7 4) Cascade buffer Enable bit: MEMT_LC00_inmux00_bram_cbit_5
(7 4) Cascade buffer Enable bit: MEMT_LC01_inmux00_bram_cbit_5
(7 4) Cascade buffer Enable bit: MEMT_LC02_inmux00_bram_cbit_5
(7 4) Cascade buffer Enable bit: MEMT_LC03_inmux00_bram_cbit_5
(7 4) Cascade buffer Enable bit: MEMT_LC04_inmux00_bram_cbit_5
(7 4) Cascade buffer Enable bit: MEMT_LC05_inmux00_bram_cbit_5
(7 4) Cascade buffer Enable bit: MEMT_LC06_inmux00_bram_cbit_5
@ -3443,7 +3439,6 @@
(7 5) Cascade bit: MEMT_LC00_inmux00_bram_cbit_4
(7 5) Cascade bit: MEMT_LC01_inmux00_bram_cbit_4
(7 5) Cascade bit: MEMT_LC02_inmux00_bram_cbit_4
(7 5) Cascade bit: MEMT_LC03_inmux00_bram_cbit_4
(7 5) Cascade bit: MEMT_LC04_inmux00_bram_cbit_4
(7 5) Cascade bit: MEMT_LC05_inmux00_bram_cbit_4
(7 5) Cascade bit: MEMT_LC06_inmux00_bram_cbit_4

View File

@ -28,6 +28,9 @@ def read_database(filename, tile_type):
line = re.sub(r"^Ram config bit:", "RamConfig", line)
line = re.sub(r"^PLL config bit:", "PLL", line)
line = re.sub(r"^Icegate Enable bit:", "Icegate", line)
line = re.sub(r"^MAC16 functional bit:", "IpConfig", line)
line = re.sub(r"^Hard IP config bit:", "IpConfig", line)
line = line.split()
if line[0] == "routing":
if line[3] == "wire_gbuf/in": line[3] = "fabout"
@ -54,7 +57,7 @@ def read_database(filename, tile_type):
elif line[0] == "ColBufCtrl":
line[1] = re.sub(r"B?IO(LEFT|RIGHT)_", "IO_", line[1])
line[1] = re.sub(r"IO_half_column_clock_enable_", "glb_netwk_", line[1])
line[1] = re.sub(r"(LH|MEM[BT])_colbuf_cntl_", "glb_netwk_", line[1])
line[1] = re.sub(r"(LH|MEM[BT]|MULT\d|IPCON)_colbuf_cntl_", "glb_netwk_", line[1])
if m.group(1) == "7":
line[1] = re.sub(r"glb_netwk_", "8k_glb_netwk_", line[1])
elif m.group(1) in ["1", "2"]:
@ -87,6 +90,10 @@ def read_database(filename, tile_type):
raw_db.append((bit, (line[0],)))
elif line[0] == "Carry_In_Mux":
continue
elif line[0] == "IpConfig":
line[1] = re.sub(r"MULT\d_bram_cbit_", "CBIT_", line[1]) #not a typo, sometimes IP config bits are in DSP tiles and use a MULT prefix...
line[1] = re.sub(r"IPCON_bram_cbit_", "CBIT_", line[1])
raw_db.append((bit, (line[0], line[1])))
else:
print("unsupported statement: %s: %s" % (bit, line))
assert False
@ -149,3 +156,11 @@ for device_class in ["5k", "8k"]:
with open("database_ramt_%s.txt" % (device_class, ), "w") as f:
for entry in read_database("bitdata_ramt_%s.txt" % (device_class, ), "ramt_" + device_class):
print("\t".join(entry), file=f)
for dsp_idx in range(4):
with open("database_dsp%d_5k.txt" % (dsp_idx, ), "w") as f:
for entry in read_database("bitdata_dsp%d_5k.txt" % (dsp_idx, ), "dsp%d_5" % (dsp_idx, )):
print("\t".join(entry), file=f)
with open("database_ipcon_5k.txt", "w") as f:
for entry in read_database("bitdata_ipcon_5k.txt", "ipcon"):
print("\t".join(entry), file=f)

View File

@ -4,10 +4,12 @@ import os
device_class = os.getenv("ICEDEVICE")
with open("../icebox/iceboxdb.py", "w") as f:
files = [ "database_io", "database_logic", "database_ramb", "database_ramt"]
files = [ "database_io", "database_logic", "database_ramb", "database_ramt", "database_ipcon_5k"]
for device_class in ["5k", "8k"]:
files.append("database_ramb_" + device_class)
files.append("database_ramt_" + device_class)
for i in range(4):
files.append("database_dsp%d_5k" % i)
for i in files:
print('%s_txt = """' % i, file=f)
with open("%s.txt" % i, "r") as fi:

View File

@ -37,8 +37,24 @@ for filename in sys.argv[1:]:
else:
cur_text_db = text_db.setdefault("ramt_" + device_class if device_class in ["5k", "8k"] else "ramt", set())
ignore = False
elif device_class == "5k" and line.startswith(("IpCon", "DSP")):
ignore = True
elif device_class == "5k" and line.startswith("IpCon"):
cur_text_db = text_db.setdefault("ipcon_5k", set())
ignore = False
elif device_class == "5k" and line.startswith("DSP"):
match = re.match(r"DSP_Tile_\d+_(\d+)", line)
ypos = int(match.group(1))
dsp_idx = None
if ypos in [5, 10, 15, 23]:
dsp_idx = 0
if ypos in [6, 11, 16, 24]:
dsp_idx = 1
if ypos in [7, 12, 17, 25]:
dsp_idx = 2
if ypos in [8, 13, 18, 26]:
dsp_idx = 3
assert dsp_idx != None
cur_text_db = text_db.setdefault("dsp%d_5k" % dsp_idx, set())
ignore = False
elif not ignore:
print("'" + line + "'")
assert line.startswith(" ")

View File

@ -7,6 +7,7 @@ device_class = os.getenv("ICEDEVICE")
if device_class == "8k":
num_ramb40 = 32
num_iobanks = 4
num_dsp = 0
pins="""
A1 A2 A5 A6 A7 A9 A10 A11 A15 A16
@ -32,6 +33,7 @@ if device_class == "8k":
elif device_class == "384":
num_ramb40 = 0
num_iobanks = 3
num_dsp = 0
pins = """
A1 A2 A3 A4 A5 A6 A7
@ -48,6 +50,7 @@ elif device_class == "384":
elif device_class == "1k":
num_ramb40 = 16
num_iobanks = 4
num_dsp = 0
pins = """
1 2 3 4 7 8 9 10 11 12 19 22 23 24 25 26 28 29 31 32 33 34
@ -60,7 +63,8 @@ elif device_class == "1k":
elif device_class == "5k":
num_ramb40 = 30
num_iobanks = 2
num_dsp = 8
num_spram256ka = 4
#TODO(tannewt): Add 39, 40, 41 to this list. It causes placement failures for some reason.
# Also add 14 15 16 17 which are constrained to SPI.
#TODO(daveshah1): Add back I3C IO 23 which cause placement failures when assigned to
@ -73,7 +77,7 @@ elif device_class == "5k":
#TODO(tannewt): Add 39, 40, 41 to this list. It causes placement failures for some reason.
gpins = "20 35 37 44".split()
led_pins = "39 40 41".split()
def output_makefile(working_dir, fuzzname):
with open(working_dir + "/Makefile", "w") as f:
print("all: %s" % " ".join(["%s_%02d.bin" % (fuzzname, i) for i in range(num)]), file=f)

View File

@ -6,26 +6,32 @@ asc_bits = set()
glb_bits = set()
# parsing .asc file
with open(argv[1]) as f:
current_tile = None
current_line = None
for line in f:
if line.startswith("."):
if line.find("_tile ") >= 0:
f = line.split()
current_tile = "%02d.%02d" % (int(f[1]), int(f[2]))
current_line = 0
else:
current_tile = None
current_line = None
continue
if current_tile is not None:
for i in range(len(line)):
if line[i] == '1':
asc_bits.add("%s.%02d.%02d" % (current_tile, current_line, i))
current_line += 1
try:
with open(argv[1]) as f:
current_tile = None
current_line = None
for line in f:
if line.startswith("."):
if line.find("_tile ") >= 0:
f = line.split()
current_tile = "%02d.%02d" % (int(f[1]), int(f[2]))
current_line = 0
else:
current_tile = None
current_line = None
continue
if current_tile is not None:
for i in range(len(line)):
if line[i] == '1':
asc_bits.add("%s.%02d.%02d" % (current_tile, current_line, i))
current_line += 1
except FileNotFoundError:
print("ASC file doesn't exist, skipping glbcheck!.")
# The asc file may not exist for innocent reasons, such as
# the icecube router failing. So exit with code 0 to keep
# the fuzz Makefile happy
exit(0)
# parsing .glb file
with open(argv[2]) as f:
current_tile = None

206
icefuzz/make_dsp.py Executable file
View File

@ -0,0 +1,206 @@
#!/usr/bin/env python3
from fuzzconfig import *
import numpy as np
import os
device_class = os.getenv("ICEDEVICE")
assert device_class == "5k"
working_dir = "work_%s_dsp" % (device_class, )
os.system("rm -rf " + working_dir)
os.mkdir(working_dir)
def randbin(n):
return "".join([np.random.choice(["0", "1"]) for i in range(n)])
#Only certain combinations are allowed in icecube, list them here
#This is not a complete set, but enough to cover all bits except cbit13, which
#is not set in any allowed config (?)
allowed_configs = ["0010000010000001001110110", "1110000010000001001110110", "0010000010000001000000000", "1110000010000001000000000",
"0000000011000001111110110", "1100000011000001111110110", "0000000011000001110000110", "0010000101000010111111111",
"0000001001100100111111111", "0001001001100100111111111", "0001101001100100111111111", "0001111000101100000000000"]
coverage = set()
for c in allowed_configs:
for i in range(25):
if c[i] == "1":
coverage.add(i)
assert len(coverage) >= 24
#print(len(coverage))
#print(coverage)
for idx in range(num):
with open(working_dir + "/dsp_%02d.v" % idx, "w") as f:
glbs = ["glb[%d]" % i for i in range(np.random.randint(8)+1)]
# TODO: ce should be on this list, but causes routing failures
glbs_choice = ["clk", "a", "b", "c", "d,", "ah", "bh", "ch", "dh", "irt", "irb", "ort", "orb", "olt", "olb", "ast", "asb", "oht", "ohb", "sei"]
print("""
module top (
input [%d:0] glb_pins,
input [%d:0] in_pins,
output [15:0] out_pins
);
wire [%d:0] glb, glb_pins;
SB_GB gbufs [%d:0] (
.USER_SIGNAL_TO_GLOBAL_BUFFER(glb_pins),
.GLOBAL_BUFFER_OUTPUT(glb)
);
""" % (len(glbs)-1, len(pins) - len(glbs) - 16 - 1, len(glbs)-1, len(glbs)-1), file=f)
bits = ["in_pins[%d]" % i for i in range(100)]
bits = list(np.random.permutation(bits))
for i in range(num_dsp):
tmp = list(np.random.permutation(bits))
bits_c = [tmp.pop() for k in range(16)]
bits_a = [tmp.pop() for k in range(16)]
bits_b = [tmp.pop() for k in range(16)]
bits_d = [tmp.pop() for k in range(16)]
bit_ce = tmp.pop()
bit_clk = tmp.pop()
bit_ahold = tmp.pop()
bit_bhold = tmp.pop()
bit_chold = tmp.pop()
bit_dhold = tmp.pop()
bit_irsttop = tmp.pop()
bit_irstbot = tmp.pop()
bit_orsttop = tmp.pop()
bit_orstbot = tmp.pop()
bit_oloadtop = tmp.pop()
bit_oloadbot = tmp.pop()
bit_addsubtop = tmp.pop()
bit_addsubbot = tmp.pop()
bit_oholdtop = tmp.pop()
bit_oholdbot = tmp.pop()
aci_opts = ["1'b0"]
if i > 0 and i % 4 != 0:
aci_opts.append("out_%d[33]" % (i-1));
sei_opts = ["1'b0"]
if i > 0 and i % 4 != 0:
sei_opts.append("out_%d[34]" % (i - 1));
bit_ci = tmp.pop()
bit_accumci = np.random.choice(aci_opts)
bit_signextin = np.random.choice(sei_opts)
if len(glbs) != 0:
s = np.random.choice(glbs_choice)
glbs_choice.remove(s)
if s == "clk": bit_clk = glbs.pop()
if s == "a": bits_a[np.random.randint(len(bits_a))] = glbs.pop()
if s == "b": bits_b[np.random.randint(len(bits_b))] = glbs.pop()
if s == "c": bits_c[np.random.randint(len(bits_c))] = glbs.pop()
if s == "d": bits_d[np.random.randint(len(bits_d))] = glbs.pop()
if s == "ah": bit_ahold = glbs.pop()
if s == "bh": bit_bhold = glbs.pop()
if s == "ch": bit_chold = glbs.pop()
if s == "dh": bit_dhold = glbs.pop()
if s == "irt": bit_irsttop = glbs.pop()
if s == "irb": bit_irstbot = glbs.pop()
if s == "ort": bit_orsttop = glbs.pop()
if s == "orb": bit_orstbot = glbs.pop()
if s == "olt": bit_oloadtop = glbs.pop()
if s == "olb": bit_oloadbot = glbs.pop()
if s == "ast": bit_addsubtop = glbs.pop()
if s == "asb": bit_addsubbot = glbs.pop()
if s == "oht": bit_oholdtop = glbs.pop()
if s == "ohb": bit_oholdbot = glbs.pop()
if s == "ci": bit_ci = glbs.pop()
bits_a = "{%s}" % ", ".join(bits_a)
bits_b = "{%s}" % ", ".join(bits_b)
bits_c = "{%s}" % ", ".join(bits_c)
bits_d = "{%s}" % ", ".join(bits_d)
negclk = randbin(1)
params = np.random.choice(allowed_configs)
params = params[::-1]
print("""
wire [34:0] out_%d;
SB_MAC16 #(
.NEG_TRIGGER(1'b%s),
.C_REG(1'b%s),
.A_REG(1'b%s),
.B_REG(1'b%s),
.D_REG(1'b%s),
.TOP_8x8_MULT_REG(1'b%s),
.BOT_8x8_MULT_REG(1'b%s),
.PIPELINE_16x16_MULT_REG1(1'b%s),
.PIPELINE_16x16_MULT_REG2(1'b%s),
.TOPOUTPUT_SELECT(2'b%s),
.TOPADDSUB_LOWERINPUT(2'b%s),
.TOPADDSUB_UPPERINPUT(1'b%s),
.TOPADDSUB_CARRYSELECT(2'b%s),
.BOTOUTPUT_SELECT(2'b%s),
.BOTADDSUB_LOWERINPUT(2'b%s),
.BOTADDSUB_UPPERINPUT(1'b%s),
.BOTADDSUB_CARRYSELECT(2'b%s),
.MODE_8x8(1'b%s),
.A_SIGNED(1'b%s),
.B_SIGNED(1'b%s)
) dsp_%d (
.CLK(%s),
.CE(%s),
.C(%s),
.A(%s),
.B(%s),
.D(%s),
.AHOLD(%s),
.BHOLD(%s),
.CHOLD(%s),
.DHOLD(%s),
.IRSTTOP(%s),
.IRSTBOT(%s),
.ORSTTOP(%s),
.ORSTBOT(%s),
.OLOADTOP(%s),
.OLOADBOT(%s),
.ADDSUBTOP(%s),
.ADDSUBBOT(%s),
.OHOLDTOP(%s),
.OHOLDBOT(%s),
.CI(%s),
.ACCUMCI(%s),
.SIGNEXTIN(%s),
.O(out_%d[31:0]),
.CO(out_%d[32]),
.ACCUMCO(out_%d[33]),
.SIGNEXTOUT(out_%d[34])
);"""
% (
i,
negclk,
params[0], params[1], params[2], params[3],
params[4], params[5], params[6], params[7],
params[8:10][::-1], params[10:12][::-1], params[12], params[13:15][::-1],
params[15:17][::-1], params[17:19][::-1], params[19], params[20:22][::-1],
params[22], params[23], params[24],
i,
bit_clk, bit_ce, bits_c, bits_a, bits_b, bits_d,
bit_ahold, bit_bhold, bit_chold, bit_dhold,
bit_irsttop, bit_irstbot, bit_orsttop, bit_orstbot,
bit_oloadtop, bit_oloadbot, bit_addsubtop, bit_addsubbot,
bit_oholdtop, bit_oholdbot,
bit_ci, bit_accumci, bit_signextin,
i, i, i, i
), file=f)
bits = list(np.random.permutation(bits))
for k in range(33):
bits[k] = "out_%d[%d] ^ %s" % (i, k, bits[k])
for k in range(16):
print("assign out_pins[%d] = out_%d[%d] ^ out_%d[%d];" % (k, i, np.random.randint(33), i, np.random.randint(33)), file=f)
print("endmodule", file=f)
with open(working_dir + "/dsp_%02d.pcf" % idx, "w") as f:
p = list(np.random.permutation(pins))
for i in range(len(pins) - len(glbs) - 16):
print("set_io in_pins[%d] %s" % (i, p.pop()), file=f)
for i in range(16):
print("set_io out_pins[%d] %s" % (i, p.pop()), file=f)
output_makefile(working_dir, "dsp")

218
icefuzz/make_upip.py Executable file
View File

@ -0,0 +1,218 @@
#!/usr/bin/env python3
from fuzzconfig import *
import numpy as np
import os
device_class = os.getenv("ICEDEVICE")
assert device_class == "5k"
working_dir = "work_%s_upip" % (device_class, )
os.system("rm -rf " + working_dir)
os.mkdir(working_dir)
def randbin(n):
return "".join([np.random.choice(["0", "1"]) for i in range(n)])
for idx in range(num):
with open(working_dir + "/upip_%02d.v" % idx, "w") as f:
glbs = ["glb[%d]" % i for i in range(np.random.randint(6)+1)]
print("""
module top (
input [%d:0] glb_pins,
input [%d:0] in_pins,
output [15:0] out_pins,
output [%d:0] led_pins
);
wire [%d:0] glb, glb_pins;
SB_GB gbufs [%d:0] (
.USER_SIGNAL_TO_GLOBAL_BUFFER(glb_pins),
.GLOBAL_BUFFER_OUTPUT(glb)
);
""" % (len(glbs)-1, len(pins) - len(glbs) - 16 - 1, len(led_pins)-1, len(glbs)-1, len(glbs)-1), file=f)
bits = ["in_pins[%d]" % (i % (len(pins) - len(glbs) - 16 - 1)) for i in range(60)]
bits = list(np.random.permutation(bits))
#Internal oscillators
tmp = ["in_pins[%d]" % i for i in range(len(pins) - len(glbs) - 16 - 1)]
tmp = list(np.random.permutation(tmp))
for osc in ["LF", "HF"]:
bit_pu = tmp.pop()
bit_en = tmp.pop()
bit_clk = "clk_" + osc
glbs.append(bit_clk)
param = ""
if osc == "HF": #only HFOSC has a divider:
param = "#(.CLKHF_DIV(\"0b%s\"))" % randbin(2)
route = np.random.choice(["", "/* synthesis ROUTE_THROUGH_FABRIC = 1 */"])
print("""
SB_%sOSC %s osc_%s (
.CLK%sPU(%s),
.CLK%sEN(%s),
.CLK%s(%s)
) %s;
""" % (
osc, param, osc, osc, bit_pu,
osc, bit_en, osc, bit_clk, route
), file=f)
glbs_orig = list(glbs)
#256k SPRAM blocks
for i in range(num_spram256ka):
tmp = list(np.random.permutation(bits))
bits_addr = [tmp.pop() for k in range(14)]
bits_mask = [tmp.pop() for k in range(4)]
bits_wdata = [tmp.pop() for k in range(16)]
bit_wren = tmp.pop()
bit_cs = tmp.pop()
bit_clock = tmp.pop()
bit_standby = tmp.pop()
bit_sleep = tmp.pop()
bit_poweroff = tmp.pop()
glbs_choice = ["clk", "a", "msk", "wd", "we", "cs", "stb", "slp", "po"]
if len(glbs) != 0:
s = np.random.choice(glbs_choice)
glbs_choice.remove(s)
if s == "clk": bit_clock = glbs.pop()
if s == "a": bits_addr[np.random.randint(len(bits_addr))] = glbs.pop()
if s == "msk": bits_mask [np.random.randint(len(bits_mask ))] = glbs.pop()
if s == "wd": bits_wdata[np.random.randint(len(bits_wdata))] = glbs.pop()
if s == "we": bit_wren = glbs.pop()
if s == "cs": bit_cs = glbs.pop()
if s == "stb": bit_standby = glbs.pop()
if s == "slp": bit_sleep = glbs.pop()
if s == "po": bit_poweroff = glbs.pop()
bits_addr = "{%s}" % ", ".join(bits_addr)
bits_mask = "{%s}" % ", ".join(bits_mask)
bits_wdata = "{%s}" % ", ".join(bits_wdata)
print("""
wire [15:0] rdata_%d;
SB_SPRAM256KA spram_%d (
.ADDRESS(%s),
.DATAIN(%s),
.MASKWREN(%s),
.WREN(%s),
.CHIPSELECT(%s),
.CLOCK(%s),
.STANDBY(%s),
.SLEEP(%s),
.POWEROFF(%s),
.DATAOUT(rdata_%d)
);
""" % (
i, i,
bits_addr, bits_wdata, bits_mask, bit_wren,
bit_cs, bit_clock, bit_standby, bit_sleep,
bit_poweroff, i
), file=f)
bits = list(np.random.permutation(bits))
if np.random.choice(["XOR", "MULT"]) == "MULT":
#stress routing at sides more with a multiply
print("""
wire [31:0] mult_res_%d;
assign mult_res_%d = rdata_%d * %s;
""" % (
i, i, i, ("{%s}" % ", ".join(bits[0:32]))
), file=f)
for k in range(32):
bits[k] = "mult_res_%d[%d]" % (i, k)
else:
for k in range(16):
bits[k] = "rdata_%d[%d] ^ %s" % (i, k, bits[k])
# Internal PWM IP
tmp = list(np.random.permutation(bits))
glbs = list(glbs_orig)
bit_cs = tmp.pop()
bit_clk = np.random.choice([glbs.pop(), tmp.pop()])
bit_rst = np.random.choice([glbs.pop(), tmp.pop()])
bit_den = tmp.pop()
bit_exe = tmp.pop()
bits_dat = [tmp.pop() for k in range(8)]
bits_addr = [tmp.pop() for k in range(4)]
print("""
wire [2:0] pwm_out;
SB_LEDDA_IP ledda (
.LEDDCS(%s),
.LEDDCLK(%s),
.LEDDDAT7(%s),
.LEDDDAT6(%s),
.LEDDDAT5(%s),
.LEDDDAT4(%s),
.LEDDDAT3(%s),
.LEDDDAT2(%s),
.LEDDDAT1(%s),
.LEDDDAT0(%s),
.LEDDADDR3(%s),
.LEDDADDR2(%s),
.LEDDADDR1(%s),
.LEDDADDR0(%s),
.LEDDDEN(%s),
.LEDDEXE(%s),
.LEDDRST(%s),
.PWMOUT0(pwm_out[0]),
.PWMOUT1(pwm_out[1]),
.PWMOUT2(pwm_out[2])
);
""" % (
bit_cs, bit_clk, bits_dat[7], bits_dat[6], bits_dat[5], bits_dat[4],
bits_dat[3], bits_dat[2], bits_dat[1], bits_dat[0], bits_addr[3],
bits_addr[2], bits_addr[1], bits_addr[0], bit_den, bit_exe, bit_rst
), file=f)
bits.append("pwm_out[0]")
bits.append("pwm_out[1]")
bits.append("pwm_out[2]")
# Constant current LED driver
current_choices = ["0b000000", "0b000001", "0b000011", "0b000111", "0b001111", "0b011111", "0b111111"]
current_modes = ["0b0", "0b1"]
currents = [np.random.choice(current_choices) for i in range(3)]
bit_curren = np.random.choice(bits)
bit_rgbleden = np.random.choice(bits)
bits_pwm = [np.random.choice([np.random.choice(bits), "pwm_out[%d]" % i]) for i in range(3)]
print("""
SB_RGBA_DRV #(
.CURRENT_MODE(\"%s\"),
.RGB0_CURRENT(\"%s\"),
.RGB1_CURRENT(\"%s\"),
.RGB2_CURRENT(\"%s\")
) rgba_drv (
.CURREN(%s),
.RGBLEDEN(%s),
.RGB0PWM(%s),
.RGB1PWM(%s),
.RGB2PWM(%s),
.RGB0(led_pins[0]),
.RGB1(led_pins[1]),
.RGB2(led_pins[2])
);
""" % (
np.random.choice(current_modes), currents[0], currents[1], currents[2],
bit_curren, bit_rgbleden, bits_pwm[0], bits_pwm[1], bits_pwm[2]
), file = f)
# TODO: I2C and SPI
print("assign out_pins = rdata_%d;" % i, file=f)
print("endmodule", file=f)
with open(working_dir + "/upip_%02d.pcf" % idx, "w") as f:
p = list(np.random.permutation(pins))
for i in range(len(pins) - len(glbs) - 16):
print("set_io in_pins[%d] %s" % (i, p.pop()), file=f)
for i in range(16):
print("set_io out_pins[%d] %s" % (i, p.pop()), file=f)
for i in range(len(led_pins)):
print("set_io led_pins[%d] %s" % (i, led_pins[i]), file=f)
output_makefile(working_dir, "upip")

1
icefuzz/tests/dsp_cbit/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
work_dsp_cbit/

View File

@ -0,0 +1,9 @@
DSP (0, 15):
Missing (0, 16, CBIT_1)
Missing (0, 16, CBIT_2)
Missing (0, 16, CBIT_3)
Missing (0, 16, CBIT_4)
New: (0, 19, CBIT_3)
New: (0, 19, CBIT_5)
New: (0, 19, CBIT_4)
New: (0, 19, CBIT_6)

View File

@ -0,0 +1,132 @@
#!/usr/bin/env python3
import os, sys
device = "up5k"
# This script is designed to determine which DSPs have configuration bits
# not in their usual position, as in some cases DSP and IPConnect tiles have
# their config bits swapped
# Unfortunately, arbitrary configurations are not allowed by icecube, so
# we define a set that gives us maximum coverage (full coverage is not
# possible as one CBIT is never set)
allowed_configs = ["1110000010000001001110110", "0010000101000010111111111", "0001111000101100000000000"]
coverage = set()
for c in allowed_configs:
for i in range(25):
if c[i] == "1":
coverage.add(i)
assert len(coverage) >= 24
def parse_exp(f):
current_x = 0
current_y = 0
bits = set()
for line in f:
splitline = line.split(' ')
if splitline[0].endswith("_tile"):
current_x = int(splitline[1])
current_y = int(splitline[2])
elif splitline[0] == "IpConfig":
if splitline[1][:5] == "CBIT_":
bitidx = int(splitline[1][5:])
bits.add((current_x, current_y, bitidx))
return bits
dsp_locs = [( 0, 5, 0), ( 0, 10, 0), ( 0, 15, 0), ( 0, 23, 0),
(25, 5, 0), (25, 10, 0), (25, 15, 0), (25, 23, 0)]
dsp_data = {}
if not os.path.exists("./work_dsp_cbit"):
os.mkdir("./work_dsp_cbit")
for loc in dsp_locs:
x, y, z = loc
missing_bits = set()
new_bits = set()
for config in allowed_configs:
params = config[::-1]
with open("./work_dsp_cbit/dsp_cbit.v","w") as f:
print("""
module top(input clk, input a, input b, input c, input d, output y);
""", file=f)
print("""
SB_MAC16 #(
.C_REG(1'b%s),
.A_REG(1'b%s),
.B_REG(1'b%s),
.D_REG(1'b%s),
.TOP_8x8_MULT_REG(1'b%s),
.BOT_8x8_MULT_REG(1'b%s),
.PIPELINE_16x16_MULT_REG1(1'b%s),
.PIPELINE_16x16_MULT_REG2(1'b%s),
.TOPOUTPUT_SELECT(2'b%s),
.TOPADDSUB_LOWERINPUT(2'b%s),
.TOPADDSUB_UPPERINPUT(1'b%s),
.TOPADDSUB_CARRYSELECT(2'b%s),
.BOTOUTPUT_SELECT(2'b%s),
.BOTADDSUB_LOWERINPUT(2'b%s),
.BOTADDSUB_UPPERINPUT(1'b%s),
.BOTADDSUB_CARRYSELECT(2'b%s),
.MODE_8x8(1'b%s),
.A_SIGNED(1'b%s),
.B_SIGNED(1'b%s)
) dsp (
.CLK(clk),
.C(c),
.A(a),
.B(b),
.D(d),
.O(y)
);"""
% (
params[0], params[1], params[2], params[3],
params[4], params[5], params[6], params[7],
params[8:10][::-1], params[10:12][::-1], params[12], params[13:15][::-1],
params[15:17][::-1], params[17:19][::-1], params[19], params[20:22][::-1],
params[22], params[23], params[24]), file=f)
print("endmodule",file=f)
with open("./work_dsp_cbit/dsp_cbit.pcf","w") as f:
print("set_location dsp %d %d %d" % loc, file=f)
retval = os.system("bash ../../icecube.sh -" + device + " ./work_dsp_cbit/dsp_cbit.v > ./work_dsp_cbit/icecube.log 2>&1")
if retval != 0:
sys.stderr.write('ERROR: icecube returned non-zero error code\n')
sys.exit(1)
retval = os.system("../../../icebox/icebox_explain.py ./work_dsp_cbit/dsp_cbit.asc > ./work_dsp_cbit/dsp_cbit.exp")
if retval != 0:
sys.stderr.write('ERROR: icebox_explain returned non-zero error code\n')
sys.exit(1)
bits = set()
known = set()
with open('./work_dsp_cbit/dsp_cbit.exp', 'r') as f:
bits = parse_exp(f)
for i in range(25):
if params[i] == "1":
exp_pos = (x, y + (i // 8), i % 8)
if exp_pos not in bits:
missing_bits.add(exp_pos)
else:
known.add(exp_pos)
for bit in bits:
if bit not in known:
new_bits.add(bit)
if len(missing_bits) > 0 or len(new_bits) > 0:
print("DSP (%d, %d):" % (x, y))
for bit in missing_bits:
print("\tMissing (%d, %d, CBIT_%d)" % bit)
for bit in new_bits:
print("\tNew: (%d, %d, CBIT_%d)" % bit)
dsp_data[loc] = (missing_bits, new_bits)
with open("dsp_cbits_%s.txt" % device, 'w') as f:
for loc in dsp_data:
x, y, z = loc
missing_bits, new_bits = dsp_data[loc]
print("DSP (%d, %d):" % (x, y), file=f)
for bit in missing_bits:
print("\tMissing (%d, %d, CBIT_%d)" % bit,file=f)
for bit in new_bits:
print("\tNew: (%d, %d, CBIT_%d)" % bit,file=f)

View File

@ -0,0 +1 @@
work_rgba_drv/

View File

@ -0,0 +1,174 @@
#!/usr/bin/env python3
import os, sys
# SB_RGBA_DRV automatic fuzzing script
device = "up5k"
# SB_RGBA_DRV config bits to be fuzzed
# These must be in an order such that a config with bit i set doesn't set any other undiscovered bits yet
fuzz_bits = [
"RGB0_CURRENT_0",
"RGB0_CURRENT_1",
"RGB0_CURRENT_2",
"RGB0_CURRENT_3",
"RGB0_CURRENT_4",
"RGB0_CURRENT_5",
"RGB1_CURRENT_0",
"RGB1_CURRENT_1",
"RGB1_CURRENT_2",
"RGB1_CURRENT_3",
"RGB1_CURRENT_4",
"RGB1_CURRENT_5",
"RGB2_CURRENT_0",
"RGB2_CURRENT_1",
"RGB2_CURRENT_2",
"RGB2_CURRENT_3",
"RGB2_CURRENT_4",
"RGB2_CURRENT_5",
"CURRENT_MODE"
]
# Boilerplate code based on the icefuzz script
code_prefix = """
module top(
input curren,
input rgbleden,
input r_in,
input g_in,
input b_in,
output r_led,
output g_led,
output b_led);
"""
def get_param_value(param_name, param_size, fuzz_bit):
param = "\"0b";
#In the RGB driver, once bit i of a current parameter is set i-1..0 must also be set
is_high = False
for i in range(param_size - 1, -1, -1):
if fuzz_bit == param_name + "_" + str(i) or (i == 0 and fuzz_bit == "CURRENT_MODE") or is_high:
param += '1'
is_high = True
else:
param += '0'
param += "\""
return param
def inst_rgba(fuzz_bit):
v = ""
v += """SB_RGBA_DRV rgba_inst (
.CURREN(curren),
.RGBLEDEN(rgbleden),
.RGB0PWM(r_in),
.RGB1PWM(g_in),
.RGB2PWM(b_in),
.RGB0(r_led),
.RGB1(g_led),
.RGB2(b_led)
);"""
v += "defparam rgba_inst.CURRENT_MODE = " + get_param_value("CURRENT_MODE", 1, fuzz_bit) + ";\n"
v += "defparam rgba_inst.RGB0_CURRENT = " + get_param_value("RGB0_CURRENT", 6, fuzz_bit) + ";\n"
v += "defparam rgba_inst.RGB1_CURRENT = " + get_param_value("RGB1_CURRENT", 6, fuzz_bit) + ";\n"
v += "defparam rgba_inst.RGB2_CURRENT = " + get_param_value("RGB2_CURRENT", 6, fuzz_bit) + ";\n"
return v;
def make_vlog(fuzz_bit):
vlog = code_prefix
vlog += inst_rgba(fuzz_bit)
vlog += "endmodule"
return vlog
known_bits = []
# Set to true to continue even if multiple bits are changed (needed because
# of the issue discusssed below)
show_all_bits = False #TODO: make this an argument
device = "up5k" #TODO: environment variable?
#HACK: icecube doesn't let you set all of the config bits to 0,
#which makes fuzzing early on annoying as there is never a case
#with just 1 bit set. So a tiny bit of semi-manual work is needed
#first to discover this (basically run this script with show_all_bits=True
#and look for the stuck bit)
#TODO: clever code could get rid of this
rgba_drv_en_bit = {
"up5k" : (0, 28, 5)
}
#Return a list of RGBA_DRIVER config bits in the format (x, y, bit)
def parse_exp(expfile):
current_x = 0
current_y = 0
bits = []
with open(expfile, 'r') as f:
for line in f:
splitline = line.split(' ')
if splitline[0].endswith("_tile"):
current_x = int(splitline[1])
current_y = int(splitline[2])
elif splitline[0] == "IpConfig":
if splitline[1][:5] == "CBIT_":
bitidx = int(splitline[1][5:])
bits.append((current_x, current_y, bitidx))
return bits
#Convert a bit tuple as returned from the above to a nice string
def bit_to_str(bit):
return "(%d, %d, \"CBIT_%d\")" % bit
#The main fuzzing function
def do_fuzz():
if not os.path.exists("./work_rgba_drv"):
os.mkdir("./work_rgba_drv")
known_bits.append(rgba_drv_en_bit[device])
with open("rgba_drv_data_" + device + ".txt", 'w') as dat:
for fuzz_bit in fuzz_bits:
vlog = make_vlog(fuzz_bit)
with open("./work_rgba_drv/rgba_drv.v", 'w') as f:
f.write(vlog)
with open("./work_rgba_drv/rgba_drv.pcf", 'w') as f:
f.write("""
set_io r_led 39
set_io g_led 40
set_io b_led 41
""")
retval = os.system("bash ../../icecube.sh -" + device + " ./work_rgba_drv/rgba_drv.v > ./work_rgba_drv/icecube.log 2>&1")
if retval != 0:
sys.stderr.write('ERROR: icecube returned non-zero error code\n')
sys.exit(1)
retval = os.system("../../../icebox/icebox_explain.py ./work_rgba_drv/rgba_drv.asc > ./work_rgba_drv/rgba_drv.exp")
if retval != 0:
sys.stderr.write('ERROR: icebox_explain returned non-zero error code\n')
sys.exit(1)
rgba_bits = parse_exp("./work_rgba_drv/rgba_drv.exp")
new_bits = []
for set_bit in rgba_bits:
if not (set_bit in known_bits):
new_bits.append(set_bit)
if len(new_bits) == 0:
sys.stderr.write('ERROR: no new bits set when setting config bit ' + fuzz_bit + '\n')
sys.exit(1)
if len(new_bits) > 1:
sys.stderr.write('ERROR: multiple new bits set when setting config bit ' + fuzz_bit + '\n')
for bit in new_bits:
sys.stderr.write('\t' + bit_to_str(bit) + '\n')
if not show_all_bits:
sys.exit(1)
if len(new_bits) == 1:
known_bits.append(new_bits[0])
#print DIVQ_0 at the right moment, as it's not fuzzed normally
if fuzz_bit == "RGB0_CURRENT_0":
print(("\"RGBA_DRV_EN\":").ljust(24) + bit_to_str(rgba_drv_en_bit[device]) + ",")
dat.write(("\"RGBA_DRV_EN\":").ljust(24) + bit_to_str(rgba_drv_en_bit[device]) + ",\n")
print(("\"" + fuzz_bit + "\":").ljust(24) + bit_to_str(new_bits[0]) + ",")
dat.write(("\"" + fuzz_bit + "\":").ljust(24) + bit_to_str(new_bits[0]) + ",\n")
do_fuzz()

View File

@ -0,0 +1,20 @@
"RGBA_DRV_EN": (0, 28, "CBIT_5"),
"RGB0_CURRENT_0": (0, 28, "CBIT_6"),
"RGB0_CURRENT_1": (0, 28, "CBIT_7"),
"RGB0_CURRENT_2": (0, 29, "CBIT_0"),
"RGB0_CURRENT_3": (0, 29, "CBIT_1"),
"RGB0_CURRENT_4": (0, 29, "CBIT_2"),
"RGB0_CURRENT_5": (0, 29, "CBIT_3"),
"RGB1_CURRENT_0": (0, 29, "CBIT_4"),
"RGB1_CURRENT_1": (0, 29, "CBIT_5"),
"RGB1_CURRENT_2": (0, 29, "CBIT_6"),
"RGB1_CURRENT_3": (0, 29, "CBIT_7"),
"RGB1_CURRENT_4": (0, 30, "CBIT_0"),
"RGB1_CURRENT_5": (0, 30, "CBIT_1"),
"RGB2_CURRENT_0": (0, 30, "CBIT_2"),
"RGB2_CURRENT_1": (0, 30, "CBIT_3"),
"RGB2_CURRENT_2": (0, 30, "CBIT_4"),
"RGB2_CURRENT_3": (0, 30, "CBIT_5"),
"RGB2_CURRENT_4": (0, 30, "CBIT_6"),
"RGB2_CURRENT_5": (0, 30, "CBIT_7"),
"CURRENT_MODE": (0, 28, "CBIT_4"),

1
icefuzz/tests/spram/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
work_spram/

174
icefuzz/tests/spram/fuzz_spram.py Executable file
View File

@ -0,0 +1,174 @@
#!/usr/bin/env python3
import os, sys, re
device = "up5k"
pins = "2 3 4 6 9 10 11 12 13 18 19 20 21 25 26 27 28 31 32 34 35 36 37 38 42 43 44 45 46 47 48".split()
# This script is designed to determine the routing of 5k SPRAM signals,
# and the location of the enable config bits
spram_locs = [(0, 0, 1), (0, 0, 2), (25, 0, 3), (25, 0, 4)]
#spram_locs = [(0, 0, 1)]
spram_data = { }
spram_signals = ["WREN", "CHIPSELECT", "CLOCK", "STANDBY", "SLEEP", "POWEROFF"]
for i in range(14):
spram_signals.append("ADDRESS[%d]" % i)
for i in range(16):
spram_signals.append("DATAIN[%d]" % i)
for i in range(16):
spram_signals.append("DATAOUT[%d]" % i)
for i in range(4):
spram_signals.append("MASKWREN[%d]" % i)
fuzz_options = ["ADDRESS", "DATAIN", "MASKWREN", "DATAOUT"]
#Parse the output of an icebox vlog file to determine connectivity
def parse_vlog(f, pin2net, net_map):
current_net = None
for line in f:
m = re.match(r"wire ([a-zA-Z0-9_]+);", line)
if m:
net = m.group(1)
mp = re.match(r"pin_([a-zA-Z0-9]+)", net)
if mp:
pin = mp.group(1)
if pin in pin2net:
current_net = pin2net[pin]
else:
current_net = None
else:
current_net = None
elif current_net is not None:
m = re.match(r"// \((\d+), (\d+), '([a-zA-Z0-9_/]+)'\)", line)
if m:
x = int(m.group(1))
y = int(m.group(2))
net = m.group(3)
if not (net.startswith("sp") or net.startswith("glb") or net.startswith("neigh") or net.startswith("io") or net.startswith("local") or net.startswith("fabout")):
net_map[current_net].add((x, y, net))
def parse_exp(f):
current_x = 0
current_y = 0
bits = set()
for line in f:
splitline = line.split(' ')
if splitline[0].endswith("_tile"):
current_x = int(splitline[1])
current_y = int(splitline[2])
elif splitline[0] == "IpConfig":
if splitline[1][:5] == "CBIT_":
bitidx = int(splitline[1][5:])
bits.add((current_x, current_y, splitline[1].strip()))
return bits
if not os.path.exists("./work_spram"):
os.mkdir("./work_spram")
for loc in spram_locs:
x, y, z = loc
net_map = {}
for sig in spram_signals:
net_map[sig] = set()
net_map["SPRAM_EN"] = set() # actually a CBIT not a net
for n in fuzz_options:
with open("./work_spram/spram.v","w") as f:
print("""
module top(
input WREN,
input CHIPSELECT,
input CLOCK,
input STANDBY,
input SLEEP,
input POWEROFF,
""", file=f)
if n == "ADDRESS":
print("\t\t\tinput [13:0] ADDRESS,", file=f)
if n == "DATAIN":
print("\t\t\tinput [15:0] DATAIN,", file=f)
if n == "MASKWREN":
print("\t\t\tinput [3:0] MASKWREN,", file=f)
if n == "DATAOUT":
print("\t\t\toutput [15:0] DATAOUT);", file=f)
else:
print("\t\t\toutput [0:0] DATAOUT);", file=f) #some dataout is always required to prevent optimisation away
addr_net = "ADDRESS" if n == "ADDRESS" else ""
din_net = "DATAIN" if n == "DATAIN" else ""
mwren_net = "MASKWREN" if n == "MASKWREN" else ""
print("""
SB_SPRAM256KA spram_i
(
.ADDRESS(%s),
.DATAIN(%s),
.MASKWREN(%s),
.WREN(WREN),
.CHIPSELECT(CHIPSELECT),
.CLOCK(CLOCK),
.STANDBY(STANDBY),
.SLEEP(SLEEP),
.POWEROFF(POWEROFF),
.DATAOUT(DATAOUT)
);
""" % (addr_net, din_net, mwren_net), file=f)
print("endmodule",file=f)
pin2net = {}
with open("./work_spram/spram.pcf","w") as f:
temp_pins = list(pins)
for sig in spram_signals:
if sig.startswith("ADDRESS") and n != "ADDRESS":
continue
if sig.startswith("DATAIN") and n != "DATAIN":
continue
if sig.startswith("MASKWREN") and n != "MASKWREN":
continue
if sig.startswith("DATAOUT") and n != "DATAOUT" and sig != "DATAOUT[0]":
continue
if len(temp_pins) == 0:
sys.stderr.write("ERROR: no remaining pins to alloc")
sys.exit(1)
pin = temp_pins.pop()
pin2net[pin] = sig
print("set_io %s %s" % (sig, pin), file=f)
print("set_location spram_i %d %d %d" % loc, file=f)
retval = os.system("bash ../../icecube.sh -" + device + " ./work_spram/spram.v > ./work_spram/icecube.log 2>&1")
if retval != 0:
sys.stderr.write('ERROR: icecube returned non-zero error code\n')
sys.exit(1)
retval = os.system("../../../icebox/icebox_explain.py ./work_spram/spram.asc > ./work_spram/spram.exp")
if retval != 0:
sys.stderr.write('ERROR: icebox_explain returned non-zero error code\n')
sys.exit(1)
retval = os.system("../../../icebox/icebox_vlog.py -l ./work_spram/spram.asc > ./work_spram/spram.vlog")
if retval != 0:
sys.stderr.write('ERROR: icebox_vlog returned non-zero error code\n')
sys.exit(1)
with open("./work_spram/spram.vlog", "r") as f:
parse_vlog(f, pin2net, net_map)
bits = []
with open("./work_spram/spram.exp", "r") as f:
bits = parse_exp(f)
net_map["SPRAM_EN"].update(bits)
spram_data[loc] = net_map
with open(device + "_spram_data.txt", "w") as f:
for loc in spram_data:
print("\t(%d, %d, %d): {" % loc, file=f)
data = spram_data[loc]
for net in sorted(data):
cnets = []
for cnet in data[net]:
cnets.append("(%d, %d, \"%s\")" % cnet)
print("\t\t%s %s, " % (("\"" + net.replace("[","_").replace("]","") + "\":").ljust(24), " ".join(cnets)), file=f)
print("\t},", file=f)

View File

@ -0,0 +1,236 @@
(0, 0, 1): {
"ADDRESS_0": (0, 2, "lutff_0/in_1"),
"ADDRESS_10": (0, 2, "lutff_2/in_0"),
"ADDRESS_11": (0, 2, "lutff_3/in_0"),
"ADDRESS_12": (0, 2, "lutff_4/in_0"),
"ADDRESS_13": (0, 2, "lutff_5/in_0"),
"ADDRESS_1": (0, 2, "lutff_1/in_1"),
"ADDRESS_2": (0, 2, "lutff_2/in_1"),
"ADDRESS_3": (0, 2, "lutff_3/in_1"),
"ADDRESS_4": (0, 2, "lutff_4/in_1"),
"ADDRESS_5": (0, 2, "lutff_5/in_1"),
"ADDRESS_6": (0, 2, "lutff_6/in_1"),
"ADDRESS_7": (0, 2, "lutff_7/in_1"),
"ADDRESS_8": (0, 2, "lutff_0/in_0"),
"ADDRESS_9": (0, 2, "lutff_1/in_0"),
"CHIPSELECT": (0, 3, "lutff_6/in_1"),
"CLOCK": (0, 1, "clk"),
"DATAIN_0": (0, 1, "lutff_0/in_3"),
"DATAIN_10": (0, 1, "lutff_2/in_1"),
"DATAIN_11": (0, 1, "lutff_3/in_1"),
"DATAIN_12": (0, 1, "lutff_4/in_1"),
"DATAIN_13": (0, 1, "lutff_5/in_1"),
"DATAIN_14": (0, 1, "lutff_6/in_1"),
"DATAIN_15": (0, 1, "lutff_7/in_1"),
"DATAIN_1": (0, 1, "lutff_1/in_3"),
"DATAIN_2": (0, 1, "lutff_2/in_3"),
"DATAIN_3": (0, 1, "lutff_3/in_3"),
"DATAIN_4": (0, 1, "lutff_4/in_3"),
"DATAIN_5": (0, 1, "lutff_5/in_3"),
"DATAIN_6": (0, 1, "lutff_6/in_3"),
"DATAIN_7": (0, 1, "lutff_7/in_3"),
"DATAIN_8": (0, 1, "lutff_0/in_1"),
"DATAIN_9": (0, 1, "lutff_1/in_1"),
"DATAOUT_0": (0, 1, "slf_op_0"),
"DATAOUT_10": (0, 2, "slf_op_2"),
"DATAOUT_11": (0, 2, "slf_op_3"),
"DATAOUT_12": (0, 2, "slf_op_4"),
"DATAOUT_13": (0, 2, "slf_op_5"),
"DATAOUT_14": (0, 2, "slf_op_6"),
"DATAOUT_15": (0, 2, "slf_op_7"),
"DATAOUT_1": (0, 1, "slf_op_1"),
"DATAOUT_2": (0, 1, "slf_op_2"),
"DATAOUT_3": (0, 1, "slf_op_3"),
"DATAOUT_4": (0, 1, "slf_op_4"),
"DATAOUT_5": (0, 1, "slf_op_5"),
"DATAOUT_6": (0, 1, "slf_op_6"),
"DATAOUT_7": (0, 1, "slf_op_7"),
"DATAOUT_8": (0, 2, "slf_op_0"),
"DATAOUT_9": (0, 2, "slf_op_1"),
"MASKWREN_0": (0, 3, "lutff_0/in_0"),
"MASKWREN_1": (0, 3, "lutff_1/in_0"),
"MASKWREN_2": (0, 3, "lutff_2/in_0"),
"MASKWREN_3": (0, 3, "lutff_3/in_0"),
"POWEROFF": (0, 4, "lutff_4/in_3"),
"SLEEP": (0, 4, "lutff_2/in_3"),
"SPRAM_EN": (0, 1, "CBIT_0"),
"STANDBY": (0, 4, "lutff_0/in_3"),
"WREN": (0, 3, "lutff_4/in_1"),
},
(0, 0, 2): {
"ADDRESS_0": (0, 2, "lutff_6/in_0"),
"ADDRESS_10": (0, 3, "lutff_0/in_1"),
"ADDRESS_11": (0, 3, "lutff_1/in_1"),
"ADDRESS_12": (0, 3, "lutff_2/in_1"),
"ADDRESS_13": (0, 3, "lutff_3/in_1"),
"ADDRESS_1": (0, 2, "lutff_7/in_0"),
"ADDRESS_2": (0, 3, "lutff_0/in_3"),
"ADDRESS_3": (0, 3, "lutff_1/in_3"),
"ADDRESS_4": (0, 3, "lutff_2/in_3"),
"ADDRESS_5": (0, 3, "lutff_3/in_3"),
"ADDRESS_6": (0, 3, "lutff_4/in_3"),
"ADDRESS_7": (0, 3, "lutff_5/in_3"),
"ADDRESS_8": (0, 3, "lutff_6/in_3"),
"ADDRESS_9": (0, 3, "lutff_7/in_3"),
"CHIPSELECT": (0, 3, "lutff_7/in_1"),
"CLOCK": (0, 2, "clk"),
"DATAIN_0": (0, 1, "lutff_0/in_0"),
"DATAIN_10": (0, 2, "lutff_2/in_3"),
"DATAIN_11": (0, 2, "lutff_3/in_3"),
"DATAIN_12": (0, 2, "lutff_4/in_3"),
"DATAIN_13": (0, 2, "lutff_5/in_3"),
"DATAIN_14": (0, 2, "lutff_6/in_3"),
"DATAIN_15": (0, 2, "lutff_7/in_3"),
"DATAIN_1": (0, 1, "lutff_1/in_0"),
"DATAIN_2": (0, 1, "lutff_2/in_0"),
"DATAIN_3": (0, 1, "lutff_3/in_0"),
"DATAIN_4": (0, 1, "lutff_4/in_0"),
"DATAIN_5": (0, 1, "lutff_5/in_0"),
"DATAIN_6": (0, 1, "lutff_6/in_0"),
"DATAIN_7": (0, 1, "lutff_7/in_0"),
"DATAIN_8": (0, 2, "lutff_0/in_3"),
"DATAIN_9": (0, 2, "lutff_1/in_3"),
"DATAOUT_0": (0, 3, "slf_op_0"),
"DATAOUT_10": (0, 4, "slf_op_2"),
"DATAOUT_11": (0, 4, "slf_op_3"),
"DATAOUT_12": (0, 4, "slf_op_4"),
"DATAOUT_13": (0, 4, "slf_op_5"),
"DATAOUT_14": (0, 4, "slf_op_6"),
"DATAOUT_15": (0, 4, "slf_op_7"),
"DATAOUT_1": (0, 3, "slf_op_1"),
"DATAOUT_2": (0, 3, "slf_op_2"),
"DATAOUT_3": (0, 3, "slf_op_3"),
"DATAOUT_4": (0, 3, "slf_op_4"),
"DATAOUT_5": (0, 3, "slf_op_5"),
"DATAOUT_6": (0, 3, "slf_op_6"),
"DATAOUT_7": (0, 3, "slf_op_7"),
"DATAOUT_8": (0, 4, "slf_op_0"),
"DATAOUT_9": (0, 4, "slf_op_1"),
"MASKWREN_0": (0, 3, "lutff_4/in_0"),
"MASKWREN_1": (0, 3, "lutff_5/in_0"),
"MASKWREN_2": (0, 3, "lutff_6/in_0"),
"MASKWREN_3": (0, 3, "lutff_7/in_0"),
"POWEROFF": (0, 4, "lutff_5/in_3"),
"SLEEP": (0, 4, "lutff_3/in_3"),
"SPRAM_EN": (0, 1, "CBIT_1"),
"STANDBY": (0, 4, "lutff_1/in_3"),
"WREN": (0, 3, "lutff_5/in_1"),
},
(25, 0, 3): {
"ADDRESS_0": (25, 2, "lutff_0/in_1"),
"ADDRESS_10": (25, 2, "lutff_2/in_0"),
"ADDRESS_11": (25, 2, "lutff_3/in_0"),
"ADDRESS_12": (25, 2, "lutff_4/in_0"),
"ADDRESS_13": (25, 2, "lutff_5/in_0"),
"ADDRESS_1": (25, 2, "lutff_1/in_1"),
"ADDRESS_2": (25, 2, "lutff_2/in_1"),
"ADDRESS_3": (25, 2, "lutff_3/in_1"),
"ADDRESS_4": (25, 2, "lutff_4/in_1"),
"ADDRESS_5": (25, 2, "lutff_5/in_1"),
"ADDRESS_6": (25, 2, "lutff_6/in_1"),
"ADDRESS_7": (25, 2, "lutff_7/in_1"),
"ADDRESS_8": (25, 2, "lutff_0/in_0"),
"ADDRESS_9": (25, 2, "lutff_1/in_0"),
"CHIPSELECT": (25, 3, "lutff_6/in_1"),
"CLOCK": (25, 1, "clk"),
"DATAIN_0": (25, 1, "lutff_0/in_3"),
"DATAIN_10": (25, 1, "lutff_2/in_1"),
"DATAIN_11": (25, 1, "lutff_3/in_1"),
"DATAIN_12": (25, 1, "lutff_4/in_1"),
"DATAIN_13": (25, 1, "lutff_5/in_1"),
"DATAIN_14": (25, 1, "lutff_6/in_1"),
"DATAIN_15": (25, 1, "lutff_7/in_1"),
"DATAIN_1": (25, 1, "lutff_1/in_3"),
"DATAIN_2": (25, 1, "lutff_2/in_3"),
"DATAIN_3": (25, 1, "lutff_3/in_3"),
"DATAIN_4": (25, 1, "lutff_4/in_3"),
"DATAIN_5": (25, 1, "lutff_5/in_3"),
"DATAIN_6": (25, 1, "lutff_6/in_3"),
"DATAIN_7": (25, 1, "lutff_7/in_3"),
"DATAIN_8": (25, 1, "lutff_0/in_1"),
"DATAIN_9": (25, 1, "lutff_1/in_1"),
"DATAOUT_0": (25, 1, "slf_op_0"),
"DATAOUT_10": (25, 2, "slf_op_2"),
"DATAOUT_11": (25, 2, "slf_op_3"),
"DATAOUT_12": (25, 2, "slf_op_4"),
"DATAOUT_13": (25, 2, "slf_op_5"),
"DATAOUT_14": (25, 2, "slf_op_6"),
"DATAOUT_15": (25, 2, "slf_op_7"),
"DATAOUT_1": (25, 1, "slf_op_1"),
"DATAOUT_2": (25, 1, "slf_op_2"),
"DATAOUT_3": (25, 1, "slf_op_3"),
"DATAOUT_4": (25, 1, "slf_op_4"),
"DATAOUT_5": (25, 1, "slf_op_5"),
"DATAOUT_6": (25, 1, "slf_op_6"),
"DATAOUT_7": (25, 1, "slf_op_7"),
"DATAOUT_8": (25, 2, "slf_op_0"),
"DATAOUT_9": (25, 2, "slf_op_1"),
"MASKWREN_0": (25, 3, "lutff_0/in_0"),
"MASKWREN_1": (25, 3, "lutff_1/in_0"),
"MASKWREN_2": (25, 3, "lutff_2/in_0"),
"MASKWREN_3": (25, 3, "lutff_3/in_0"),
"POWEROFF": (25, 4, "lutff_4/in_3"),
"SLEEP": (25, 4, "lutff_2/in_3"),
"SPRAM_EN": (25, 1, "CBIT_0"),
"STANDBY": (25, 4, "lutff_0/in_3"),
"WREN": (25, 3, "lutff_4/in_1"),
},
(25, 0, 4): {
"ADDRESS_0": (25, 2, "lutff_6/in_0"),
"ADDRESS_10": (25, 3, "lutff_0/in_1"),
"ADDRESS_11": (25, 3, "lutff_1/in_1"),
"ADDRESS_12": (25, 3, "lutff_2/in_1"),
"ADDRESS_13": (25, 3, "lutff_3/in_1"),
"ADDRESS_1": (25, 2, "lutff_7/in_0"),
"ADDRESS_2": (25, 3, "lutff_0/in_3"),
"ADDRESS_3": (25, 3, "lutff_1/in_3"),
"ADDRESS_4": (25, 3, "lutff_2/in_3"),
"ADDRESS_5": (25, 3, "lutff_3/in_3"),
"ADDRESS_6": (25, 3, "lutff_4/in_3"),
"ADDRESS_7": (25, 3, "lutff_5/in_3"),
"ADDRESS_8": (25, 3, "lutff_6/in_3"),
"ADDRESS_9": (25, 3, "lutff_7/in_3"),
"CHIPSELECT": (25, 3, "lutff_7/in_1"),
"CLOCK": (25, 2, "clk"),
"DATAIN_0": (25, 1, "lutff_0/in_0"),
"DATAIN_10": (25, 2, "lutff_2/in_3"),
"DATAIN_11": (25, 2, "lutff_3/in_3"),
"DATAIN_12": (25, 2, "lutff_4/in_3"),
"DATAIN_13": (25, 2, "lutff_5/in_3"),
"DATAIN_14": (25, 2, "lutff_6/in_3"),
"DATAIN_15": (25, 2, "lutff_7/in_3"),
"DATAIN_1": (25, 1, "lutff_1/in_0"),
"DATAIN_2": (25, 1, "lutff_2/in_0"),
"DATAIN_3": (25, 1, "lutff_3/in_0"),
"DATAIN_4": (25, 1, "lutff_4/in_0"),
"DATAIN_5": (25, 1, "lutff_5/in_0"),
"DATAIN_6": (25, 1, "lutff_6/in_0"),
"DATAIN_7": (25, 1, "lutff_7/in_0"),
"DATAIN_8": (25, 2, "lutff_0/in_3"),
"DATAIN_9": (25, 2, "lutff_1/in_3"),
"DATAOUT_0": (25, 3, "slf_op_0"),
"DATAOUT_10": (25, 4, "slf_op_2"),
"DATAOUT_11": (25, 4, "slf_op_3"),
"DATAOUT_12": (25, 4, "slf_op_4"),
"DATAOUT_13": (25, 4, "slf_op_5"),
"DATAOUT_14": (25, 4, "slf_op_6"),
"DATAOUT_15": (25, 4, "slf_op_7"),
"DATAOUT_1": (25, 3, "slf_op_1"),
"DATAOUT_2": (25, 3, "slf_op_2"),
"DATAOUT_3": (25, 3, "slf_op_3"),
"DATAOUT_4": (25, 3, "slf_op_4"),
"DATAOUT_5": (25, 3, "slf_op_5"),
"DATAOUT_6": (25, 3, "slf_op_6"),
"DATAOUT_7": (25, 3, "slf_op_7"),
"DATAOUT_8": (25, 4, "slf_op_0"),
"DATAOUT_9": (25, 4, "slf_op_1"),
"MASKWREN_0": (25, 3, "lutff_4/in_0"),
"MASKWREN_1": (25, 3, "lutff_5/in_0"),
"MASKWREN_2": (25, 3, "lutff_6/in_0"),
"MASKWREN_3": (25, 3, "lutff_7/in_0"),
"POWEROFF": (25, 4, "lutff_5/in_3"),
"SLEEP": (25, 4, "lutff_3/in_3"),
"SPRAM_EN": (25, 1, "CBIT_1"),
"STANDBY": (25, 4, "lutff_1/in_3"),
"WREN": (25, 3, "lutff_5/in_1"),
},

View File

@ -703,7 +703,7 @@ void FpgaConfig::read_ascii(std::istream &ifs)
continue;
}
if (command == ".io_tile" || command == ".logic_tile" || command == ".ramb_tile" || command == ".ramt_tile" || command.substr(0, 4) == ".dsp" || command == ".ipconn_tile")
if (command == ".io_tile" || command == ".logic_tile" || command == ".ramb_tile" || command == ".ramt_tile" || command.substr(0, 4) == ".dsp" || command == ".ipcon_tile")
{
if (!got_device)
error("Missing .device statement before %s.\n", command.c_str());
@ -1032,7 +1032,7 @@ string FpgaConfig::tile_type(int x, int y) const
return "dsp2";
if( (y == 8) || (y == 13) || (y == 18) || (y == 26))
return "dsp3";
return "ipconn";
return "ipcon";
}
if ((x == 0 || x == this->chip_width()+1) || (y == 0 || y == this->chip_height()+1)) return "io";
@ -1064,7 +1064,7 @@ int FpgaConfig::tile_width(const string &type) const
if (type == "ramt") return 42;
if (type == "io") return 18;
if (type.substr(0, 3) == "dsp") return 54;
if (type == "ipconn") return 54;
if (type == "ipcon") return 54;
panic("Unknown tile type '%s'.\n", type.c_str());
}