mirror of https://github.com/YosysHQ/icestorm.git
Merge pull request #109 from daveshah1/up5k
Support for new UltraPlus features
This commit is contained in:
commit
6e9a2da5c4
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 – UltraPlus Features Documentation</title>
|
||||
</head><body>
|
||||
<h1>Project IceStorm – 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Ω</td><td>cf_bit_32<br/>B7[10]</td><td>cf_bit_36<br/>B13[10]</td></tr>
|
||||
<tr><td>6.8kΩ</td><td>cf_bit_33<br/>B6[10]</td><td>cf_bit_37<br/>B12[10]</td></tr>
|
||||
<tr><td>10kΩ</td><td>cf_bit_34<br/>B7[15]</td><td>cf_bit_38<br/>B13[15]</td></tr>
|
||||
<tr><td>100kΩ<br/>(default)</td><td>!cf_bit_35<br/>!B6[15]</td><td>!cf_bit_39<br/>!B12[15]</td></tr>
|
||||
|
||||
</table>
|
||||
</body></html>
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
example.bin
|
||||
example.blif
|
||||
example.asc
|
||||
example.rpt
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
module top (
|
||||
input btn,
|
||||
output LED0,
|
||||
output LED1,
|
||||
);
|
||||
|
||||
assign LED0 = !btn;
|
||||
assign LED1 = btn;
|
||||
|
||||
endmodule
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
set_io LED0 12
|
||||
set_io LED1 21
|
||||
set_io btn 26
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
*.bin
|
||||
*.blif
|
||||
*.asc
|
||||
*.rpt
|
||||
*.glb
|
||||
*.psb
|
||||
*.sdf
|
||||
*.vsb
|
||||
*.bin
|
||||
*.tmp/
|
||||
*.exp
|
||||
*.vlog
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
set_io clk 44
|
||||
set_io rstn 27
|
||||
set_io LED1 12
|
||||
set_io LED2 13
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
*.bin
|
||||
*.blif
|
||||
*.asc
|
||||
*.rpt
|
||||
*.glb
|
||||
*.psb
|
||||
*.sdf
|
||||
*.vsb
|
||||
*.bin
|
||||
*.tmp/
|
||||
*.exp
|
||||
*.vlog
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
set_io RGB0 39
|
||||
set_io RGB1 40
|
||||
set_io RGB2 41
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
663
icebox/icebox.py
663
icebox/icebox.py
|
|
@ -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],
|
||||
|
|
|
|||
|
|
@ -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()):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
6397
icebox/iceboxdb.py
6397
icebox/iceboxdb.py
File diff suppressed because it is too large
Load Diff
|
|
@ -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:
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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(" ")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
@ -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")
|
||||
|
|
@ -0,0 +1 @@
|
|||
work_dsp_cbit/
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -0,0 +1 @@
|
|||
work_rgba_drv/
|
||||
|
|
@ -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()
|
||||
|
|
@ -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"),
|
||||
|
|
@ -0,0 +1 @@
|
|||
work_spram/
|
||||
|
|
@ -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)
|
||||
|
|
@ -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"),
|
||||
},
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue