library ieee;
use ieee.std_logic_1164.all;
package corelib_Dict is
-- generic (
-- type KEY_TYPE;
-- type VALUE_TYPE;
-- function to_hash(d : in KEY_TYPE, size : positive) return natural;
-- INIT_SIZE : natural := 128
-- );
-- REMOVE when using package generics
constant INIT_SIZE : positive := 128;
alias to_hash is "mod" [integer, integer return integer];
subtype KEY_TYPE is integer;
subtype VALUE_TYPE is std_logic_vector;
type PT_DICT is protected
procedure Set (constant key : in KEY_TYPE; constant data : in VALUE_TYPE);
procedure Get (constant key : in KEY_TYPE; data : out VALUE_TYPE);
impure function Get (constant key : KEY_TYPE) return VALUE_TYPE;
procedure Del (constant key : in KEY_TYPE);
procedure Clear;
impure function HasKey (constant key : KEY_TYPE) return boolean;
impure function Count return natural;
end protected PT_DICT;
procedure Merge(d0 : inout PT_DICT; d1 : inout PT_DICT; dout : inout PT_DICT);
end package corelib_Dict;
package body corelib_Dict is
type t_key_ptr is access KEY_TYPE;
type t_data_ptr is access VALUE_TYPE;
type PT_DICT is protected body
type t_entry;
type t_entry_ptr is access t_entry;
type t_entry is record
key : t_key_ptr;
data : t_data_ptr;
last_entry : t_entry_ptr;
next_entry : t_entry_ptr;
end record t_entry;
type t_entry_array is array (0 to INIT_SIZE-1) of t_entry_ptr;
variable head : t_entry_array := (others => null);
variable entry_count : integer_vector(0 to INIT_SIZE-1) := (others => 0);
-- Private method to find entry stored in dictionary
impure function Find (constant key : KEY_TYPE) return t_entry_ptr;
impure function Find (constant key : KEY_TYPE) return t_entry_ptr is
variable entry : t_entry_ptr := head(to_hash(key, INIT_SIZE));
begin
while (entry /= null) loop
if (entry.key.all = key) then
return entry;
end if;
entry := entry.last_entry;
end loop;
return null;
end function Find;
procedure Set (constant key : in KEY_TYPE; constant data : in VALUE_TYPE) is
variable addr : natural := 0;
variable entry : t_entry_ptr := Find(key);
begin
if (entry = null) then
addr := to_hash(key, INIT_SIZE);
if (head(addr) /= null) then
entry := new t_entry;
entry.key := new KEY_TYPE'(key);
entry.data := new VALUE_TYPE'(data);
entry.last_entry := head(addr);
entrypre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */#!/usr/bin/env python3
from argparse import ArgumentParser
from io import StringIO
from enum import Enum, auto
import os.path
import sys
import re
class Cell:
def __init__(self, name, keep=False, port_attrs={}):
self.name = name
self.keep = keep
self.port_attrs = port_attrs
CELLS = [
# Design element types listed in:
# - UG607 (Spartan 3)
# - UG613 (Spartan 3A)
# - UG617 (Spartan 3E)
# - UG615 (Spartan 6)
# - UG619 (Virtex 4)
# - UG621 (Virtex 5)
# - UG623 (Virtex 6)
# - UG953 (Series 7)
# - UG974 (Ultrascale)
# CLB -- RAM/ROM.
# Cell('RAM16X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM16X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM32X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM32X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM64X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM64X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM128X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM128X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM256X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM512X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM16X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM32X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM64X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM16X4S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM32X4S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM16X8S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM32X8S', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM16X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM16X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM32X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM32X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM64X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM64X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM128X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM256X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM32M', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM32M16', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM64M', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM64M8', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM32X16DR8', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM64X8SW', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('ROM16X1'),
# Cell('ROM32X1'),
# Cell('ROM64X1'),
# Cell('ROM128X1'),
# Cell('ROM256X1'),
# CLB -- registers/latches.
# Virtex 1/2/4/5, Spartan 3.
# Cell('FDCPE', port_attrs={'C': ['clkbuf_sink']}),
# Cell('FDRSE', port_attrs={'C': ['clkbuf_sink']}),
# Cell('LDCPE', port_attrs={'C': ['clkbuf_sink']}),
# Virtex 6, Spartan 6, Series 7, Ultrascale.
# Cell('FDCE'),
# Cell('FDPE'),
# Cell('FDRE'),
# Cell('FDSE'),
# Cell('LDCE'),
# Cell('LDPE'),
# Cell('AND2B1L'),
# Cell('OR2L'),
# CLB -- other.
# Cell('LUT1'),
# Cell('LUT2'),
# Cell('LUT3'),
# Cell('LUT4'),
# Cell('LUT5'),
# Cell('LUT6'),
# Cell('LUT6_2'),
# Cell('MUXF5'),
# Cell('MUXF6'),
# Cell('MUXF7'),
# Cell('MUXF8'),
# Cell('MUXF9'),
# Cell('CARRY4'),
# Cell('CARRY8'),
# Cell('MUXCY'),
# Cell('XORCY'),
# Cell('ORCY'),
# Cell('MULT_AND'),
# Cell('SRL16', port_attrs={'CLK': ['clkbuf_sink']}),
# Cell('SRL16E', port_attrs={'CLK': ['clkbuf_sink']}),
# Cell('SRLC16', port_attrs={'CLK': ['clkbuf_sink']}),
# Cell('SRLC16E', port_attrs={'CLK': ['clkbuf_sink']}),
# Cell('SRLC32E', port_attrs={'CLK': ['clkbuf_sink']}),
# Cell('CFGLUT5', port_attrs={'CLK': ['clkbuf_sink']}),
# Block RAM.
# Virtex.
# TODO: RAMB4_*
# Virtex 2, Spartan 3.
Cell('RAMB16_S1', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('RAMB16_S2', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('RAMB16_S4', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('RAMB16_S9', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('RAMB16_S18', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('RAMB16_S36', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('RAMB16_S1_S1', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S1_S2', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S1_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S1_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S1_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S1_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S2_S2', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S2_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S2_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S2_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S2_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S4_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S4_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S4_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S4_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S9_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S9_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S9_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S18_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S18_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16_S36_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
# Spartan 3A (in addition to above).
Cell('RAMB16BWE_S18', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('RAMB16BWE_S36', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('RAMB16BWE_S18_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16BWE_S18_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16BWE_S36_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16BWE_S36_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB16BWE_S36_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
# Spartan 3A DSP.
Cell('RAMB16BWER', port_attrs={ 'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
# Spartan 6 (in addition to above).
Cell('RAMB8BWER', port_attrs={ 'CLKAWRCLK': ['clkbuf_sink'], 'CLKBRDCLK': ['clkbuf_sink']}),
# Virtex 4.
Cell('FIFO16', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
Cell('RAMB16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB32_S64_ECC', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
# Virtex 5.
Cell('FIFO18', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
Cell('FIFO18_36', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
Cell('FIFO36', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
Cell('FIFO36_72', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
Cell('RAMB18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
Cell('RAMB18SDP', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
Cell('RAMB36SDP', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
# Virtex 6 / Series 7.
Cell('FIFO18E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
Cell('FIFO36E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
#Cell('RAMB18E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']]}),
#Cell('RAMB36E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']]}),
# Ultrascale.
Cell('FIFO18E2', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
Cell('FIFO36E2', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
Cell('RAMB18E2', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}),
Cell('RAMB36E2', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}),
# Ultra RAM.
Cell('URAM288', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('URAM288_BASE', port_attrs={'CLK': ['clkbuf_sink']}),
# Multipliers and DSP.
# Cell('MULT18X18'), # Virtex 2, Spartan 3
# Cell('MULT18X18S', port_attrs={'C': ['clkbuf_sink']}), # Spartan 3
# Cell('MULT18X18SIO', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3E
# Cell('DSP48A', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3A DSP
# Cell('DSP48A1', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 6
# Cell('DSP48', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 4
Cell('DSP48E', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 5
#Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 6 / Series 7
Cell('DSP48E2', port_attrs={'CLK': ['clkbuf_sink']}), # Ultrascale
# I/O logic.
# Virtex 2, Spartan 3.
# Note: these two are not officially listed in the HDL library guide, but
# they are more fundamental than OFDDR* and are necessary to construct
# differential DDR outputs (OFDDR* can only do single-ended).
Cell('FDDRCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}),
Cell('FDDRRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}),
Cell('IFDDRCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'D': ['iopad_external_pin']}),
Cell('IFDDRRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'D': ['iopad_external_pin']}),
Cell('OFDDRCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'Q': ['iopad_external_pin']}),
Cell('OFDDRRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'Q': ['iopad_external_pin']}),
Cell('OFDDRTCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'O': ['iopad_external_pin']}),
Cell('OFDDRTRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'O': ['iopad_external_pin']}),
# Spartan 3E.
Cell('IDDR2', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}),
Cell('ODDR2', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}),
# Virtex 4.
Cell('IDDR', port_attrs={'C': ['clkbuf_sink']}),
Cell('IDDR_2CLK', port_attrs={'C': ['clkbuf_sink'], 'CB': ['clkbuf_sink']}),
Cell('ODDR', port_attrs={'C': ['clkbuf_sink']}),
Cell('IDELAYCTRL', keep=True, port_attrs={'REFCLK': ['clkbuf_sink']}),
Cell('IDELAY', port_attrs={'C': ['clkbuf_sink']}),
Cell('ISERDES', port_attrs={
'CLK': ['clkbuf_sink'],
'OCLK': ['clkbuf_sink'],
'CLKDIV': ['clkbuf_sink'],
}),
Cell('OSERDES', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
# Virtex 5.
Cell('IODELAY', port_attrs={'C': ['clkbuf_sink']}),
Cell('ISERDES_NODELAY', port_attrs={
'CLK': ['clkbuf_sink'],
'CLKB': ['clkbuf_sink'],
'OCLK': ['clkbuf_sink'],
'CLKDIV': ['clkbuf_sink'],
}),
# Virtex 6.
Cell('IODELAYE1', port_attrs={'C': ['clkbuf_sink']}),
Cell('ISERDESE1', port_attrs={
'CLK': ['clkbuf_sink'],
'CLKB': ['clkbuf_sink'],
'OCLK': ['clkbuf_sink'],
'CLKDIV': ['clkbuf_sink'],
}),
Cell('OSERDESE1', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
# Series 7.
Cell('IDELAYE2', port_attrs={'C': ['clkbuf_sink']}),
Cell('ODELAYE2', port_attrs={'C': ['clkbuf_sink']}),
Cell('ISERDESE2', port_attrs={
'CLK': ['clkbuf_sink'],
'CLKB': ['clkbuf_sink'],
'OCLK': ['clkbuf_sink'],
'OCLKB': ['clkbuf_sink'],
'CLKDIV': ['clkbuf_sink'],
'CLKDIVP': ['clkbuf_sink'],
}),
Cell('OSERDESE2', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
Cell('PHASER_IN', keep=True),
Cell('PHASER_IN_PHY', keep=True),
Cell('PHASER_OUT', keep=True),
Cell('PHASER_OUT_PHY', keep=True),
Cell('PHASER_REF', keep=True),
Cell('PHY_CONTROL', keep=True),
# Ultrascale.
Cell('IDDRE1', port_attrs={'C': ['clkbuf_sink'], 'CB': ['clkbuf_sink']}),
Cell('ODDRE1', port_attrs={'C': ['clkbuf_sink']}),
Cell('IDELAYE3', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('ODELAYE3', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('ISERDESE3', port_attrs={
'CLK': ['clkbuf_sink'],
'CLK_B': ['clkbuf_sink'],
'FIFO_RD_CLK': ['clkbuf_sink'],
'CLKDIV': ['clkbuf_sink'],
}),
Cell('OSERDESE3', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
Cell('BITSLICE_CONTROL', keep=True),
Cell('RIU_OR', keep=True),
Cell('RX_BITSLICE'),
Cell('RXTX_BITSLICE'),
Cell('TX_BITSLICE'),
Cell('TX_BITSLICE_TRI'),
# Spartan 6.
Cell('IODELAY2', port_attrs={'IOCLK0': ['clkbuf_sink'], 'IOCLK1': ['clkbuf_sink'], 'CLK': ['clkbuf_sink']}),
Cell('IODRP2', port_attrs={'IOCLK0': ['clkbuf_sink'], 'IOCLK1': ['clkbuf_sink'], 'CLK': ['clkbuf_sink']}),
Cell('IODRP2_MCB', port_attrs={'IOCLK0': ['clkbuf_sink'], 'IOCLK1': ['clkbuf_sink'], 'CLK': ['clkbuf_sink']}),
Cell('ISERDES2', port_attrs={
'CLK0': ['clkbuf_sink'],
'CLK1': ['clkbuf_sink'],
'CLKDIV': ['clkbuf_sink'],
}),
Cell('OSERDES2', port_attrs={
'CLK0': ['clkbuf_sink'],
'CLK1': ['clkbuf_sink'],
'CLKDIV': ['clkbuf_sink'],
}),
# I/O buffers.
# Input.
# Cell('IBUF', port_attrs={'I': ['iopad_external_pin']}),
Cell('IBUF_DLY_ADJ', port_attrs={'I': ['iopad_external_pin']}),
Cell('IBUF_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin']}),
Cell('IBUF_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin']}),
Cell('IBUF_ANALOG', port_attrs={'I': ['iopad_external_pin']}),
Cell('IBUFE3', port_attrs={'I': ['iopad_external_pin']}),
Cell('IBUFDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('IBUFDS_DLY_ADJ', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('IBUFDS_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('IBUFDS_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('IBUFDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('IBUFDS_DIFF_OUT_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('IBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('IBUFDSE3', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('IBUFDS_DPHY', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
# Cell('IBUFG', port_attrs={'I': ['iopad_external_pin']}),
Cell('IBUFGDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('IBUFGDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
# I/O.
# Cell('IOBUF', port_attrs={'IO': ['iopad_external_pin']}),
Cell('IOBUF_DCIEN', port_attrs={'IO': ['iopad_external_pin']}),
Cell('IOBUF_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin']}),
Cell('IOBUFE3', port_attrs={'IO': ['iopad_external_pin']}),
Cell('IOBUFDS', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
Cell('IOBUFDS_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
Cell('IOBUFDS_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
Cell('IOBUFDS_DIFF_OUT', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
Cell('IOBUFDS_DIFF_OUT_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
Cell('IOBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
Cell('IOBUFDSE3', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
# Output.
# Cell('OBUF', port_attrs={'O': ['iopad_external_pin']}),
Cell('OBUFDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
Cell('OBUFDS_DPHY', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
# Output + tristate.
# Cell('OBUFT', port_attrs={'O': ['iopad_external_pin']}),
Cell('OBUFTDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
# Pulls.
Cell('KEEPER'),
Cell('PULLDOWN'),
Cell('PULLUP'),
# Misc.
Cell('DCIRESET', keep=True),
Cell('HPIO_VREF', keep=True), # Ultrascale
# Clock buffers (global).
# Cell('BUFG', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFGCE', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFGCE_1', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFGMUX', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFGMUX_1', port_attrs={'O': ['clkbuf_driver']}),
#Cell('BUFGCTRL', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFGMUX_CTRL', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFGMUX_VIRTEX4', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFG_GT', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFG_GT_SYNC'),
Cell('BUFG_PS', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFGCE_DIV', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFH', port_attrs={'O': ['clkbuf_driver']}),
#Cell('BUFHCE', port_attrs={'O': ['clkbuf_driver']}),
# Clock buffers (IO) -- Spartan 6.
Cell('BUFIO2', port_attrs={'IOCLK': ['clkbuf_driver'], 'DIVCLK': ['clkbuf_driver']}),
Cell('BUFIO2_2CLK', port_attrs={'IOCLK': ['clkbuf_driver'], 'DIVCLK': ['clkbuf_driver']}),
Cell('BUFIO2FB', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFPLL', port_attrs={'IOCLK': ['clkbuf_driver']}),
Cell('BUFPLL_MCB', port_attrs={'IOCLK0': ['clkbuf_driver'], 'IOCLK1': ['clkbuf_driver']}),
# Clock buffers (IO and regional) -- Virtex.
Cell('BUFIO', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFIODQS', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFR', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFMR', port_attrs={'O': ['clkbuf_driver']}),
Cell('BUFMRCE', port_attrs={'O': ['clkbuf_driver']}),
# Clock components.
# VIrtex.
# TODO: CLKDLL
# TODO: CLKDLLE
# TODO: CLKDLLHF
# Virtex 2, Spartan 3.
Cell('DCM'),
# Spartan 3E.
Cell('DCM_SP'),
# Spartan 6 (also uses DCM_SP and PLL_BASE).
Cell('DCM_CLKGEN'),
# Virtex 4/5.
Cell('DCM_ADV'),
Cell('DCM_BASE'),
Cell('DCM_PS'),
# Virtex 4.
Cell('PMCD'),
# Virtex 5.
Cell('PLL_ADV'),
Cell('PLL_BASE'),
# Virtex 6.
Cell('MMCM_ADV'),
Cell('MMCM_BASE'),
# Series 7.
Cell('MMCME2_ADV'),
Cell('MMCME2_BASE'),
Cell('PLLE2_ADV'),
Cell('PLLE2_BASE'),
# Ultrascale.
Cell('MMCME3_ADV'),
Cell('MMCME3_BASE'),
Cell('PLLE3_ADV'),
Cell('PLLE3_BASE'),
# Ultrascale+.
Cell('MMCME4_ADV'),
Cell('MMCME4_BASE'),
Cell('PLLE4_ADV'),
Cell('PLLE4_BASE'),
# Misc stuff.
Cell('BUFT'),
# Series 7 I/O FIFOs.
Cell('IN_FIFO', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
Cell('OUT_FIFO', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
# Ultrascale special synchronizer register.
Cell('HARD_SYNC', port_attrs={'CLK': ['clkbuf_sink']}),
# Singletons.
# Startup.
# TODO: STARTUP_VIRTEX
# TODO: STARTUP_VIRTEX2
Cell('STARTUP_SPARTAN3', keep=True),
Cell('STARTUP_SPARTAN3E', keep=True),
Cell('STARTUP_SPARTAN3A', keep=True),
Cell('STARTUP_SPARTAN6', keep=True),
Cell('STARTUP_VIRTEX4', keep=True),
Cell('STARTUP_VIRTEX5', keep=True),
Cell('STARTUP_VIRTEX6', keep=True),
Cell('STARTUPE2', keep=True), # Series 7
Cell('STARTUPE3', keep=True), # Ultrascale
# Capture trigger.
# TODO: CAPTURE_VIRTEX
# TODO: CAPTURE_VIRTEX2
Cell('CAPTURE_SPARTAN3', keep=True),
Cell('CAPTURE_SPARTAN3A', keep=True),
Cell('CAPTURE_VIRTEX4', keep=True),
Cell('CAPTURE_VIRTEX5', keep=True),
Cell('CAPTURE_VIRTEX6', keep=True),
Cell('CAPTUREE2', keep=True), # Series 7
# Internal Configuration Access Port.
# TODO: ICAP_VIRTEX2
Cell('ICAP_SPARTAN3A', keep=True),
Cell('ICAP_SPARTAN6', keep=True),
Cell('ICAP_VIRTEX4', keep=True),
Cell('ICAP_VIRTEX5', keep=True),
Cell('ICAP_VIRTEX6', keep=True),
Cell('ICAPE2', keep=True), # Series 7
Cell('ICAPE3', keep=True), # Ultrascale
# JTAG.
# TODO: BSCAN_VIRTEX
# TODO: BSCAN_VIRTEX2
Cell('BSCAN_SPARTAN3', keep=True),
Cell('BSCAN_SPARTAN3A', keep=True),
Cell('BSCAN_SPARTAN6', keep=True),
Cell('BSCAN_VIRTEX4', keep=True),
Cell('BSCAN_VIRTEX5', keep=True),
Cell('BSCAN_VIRTEX6', keep=True),
Cell('BSCANE2', keep=True), # Series 7, Ultrascale
# DNA port.
Cell('DNA_PORT'), # Virtex 5/6, Series 7, Spartan 3A/6
Cell('DNA_PORTE2'), # Ultrascale
# Frame ECC.
Cell('FRAME_ECC_VIRTEX4'),
Cell('FRAME_ECC_VIRTEX5'),
Cell('FRAME_ECC_VIRTEX6'),
Cell('FRAME_ECCE2'), # Series 7
Cell('FRAME_ECCE3'), # Ultrascale
Cell('FRAME_ECCE4'), # Ultrascale+
# AXSS command access.
Cell('USR_ACCESS_VIRTEX4'),
Cell('USR_ACCESS_VIRTEX5'),
Cell('USR_ACCESS_VIRTEX6'),
Cell('USR_ACCESSE2'), # Series 7, Ultrascale
# Misc.
Cell('POST_CRC_INTERNAL'), # Spartan 6
Cell('SUSPEND_SYNC', keep=True), # Spartan 6
Cell('KEY_CLEAR', keep=True), # Virtex 5
Cell('MASTER_JTAG', keep=True), # Ultrascale
Cell('SPI_ACCESS', keep=True), # Spartan 3AN
Cell('EFUSE_USR'),
# ADC.
Cell('SYSMON', keep=True), # Virtex 5/6
Cell('XADC', keep=True), # Series 7
Cell('SYSMONE1', keep=True), # Ultrascale
Cell('SYSMONE4', keep=True), # Ultrascale+
# Gigabit transceivers.
# Spartan 6.
Cell('GTPA1_DUAL'),
# Virtex 2 Pro.
# TODO: GT_*
# TODO: GT10_*
# Virtex 4.
Cell('GT11_CUSTOM'),
Cell('GT11_DUAL'),
Cell('GT11CLK'),
Cell('GT11CLK_MGT'),
# Virtex 5.
Cell('GTP_DUAL'),
Cell('GTX_DUAL'),
Cell('CRC32', port_attrs={'CRCCLK': ['clkbuf_sink']}),
Cell('CRC64', port_attrs={'CRCCLK': ['clkbuf_sink']}),
# Virtex 6.
Cell('GTHE1_QUAD'),
Cell('GTXE1'),
Cell('IBUFDS_GTXE1', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('IBUFDS_GTHE1', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
# Series 7.
Cell('GTHE2_CHANNEL'),
Cell('GTHE2_COMMON'),
Cell('GTPE2_CHANNEL'),
Cell('GTPE2_COMMON'),
Cell('GTXE2_CHANNEL'),
Cell('GTXE2_COMMON'),
Cell('IBUFDS_GTE2', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
# Ultrascale.
Cell('GTHE3_CHANNEL'),
Cell('GTHE3_COMMON'),
Cell('GTYE3_CHANNEL'),
Cell('GTYE3_COMMON'),
Cell('IBUFDS_GTE3', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('OBUFDS_GTE3', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
Cell('OBUFDS_GTE3_ADV', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
# Ultrascale+.
Cell('GTHE4_CHANNEL'),
Cell('GTHE4_COMMON'),
Cell('GTYE4_CHANNEL'),
Cell('GTYE4_COMMON'),
Cell('IBUFDS_GTE4', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('OBUFDS_GTE4', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
Cell('OBUFDS_GTE4_ADV', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
# Ultrascale+ GTM.
Cell('GTM_DUAL'), # not in the libraries guide
Cell('IBUFDS_GTM', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('OBUFDS_GTM', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
Cell('OBUFDS_GTM_ADV', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
# High-speed ADC/DAC.
Cell('HSDAC'), # not in libraries guide
Cell('HSADC'), # not in libraries guide
Cell('RFDAC'), # not in libraries guide
Cell('RFADC'), # not in libraries guide
# PCIE IP.
Cell('PCIE_A1'), # Spartan 6
Cell('PCIE_EP'), # Virtex 5
Cell('PCIE_2_0'), # Virtex 6
Cell('PCIE_2_1'), # Series 7
Cell('PCIE_3_0'), # Series 7
Cell('PCIE_3_1'), # Ultrascale
Cell('PCIE40E4'), # Ultrascale+
Cell('PCIE4CE4'), # Ultrascale+ v2 (not in the libraries guide)
# Ethernet IP.
Cell('EMAC'), # Virtex 4
Cell('TEMAC'), # Virtex 5
Cell('TEMAC_SINGLE'), # Virtex 6
Cell('CMAC'), # Ultrascale
Cell('CMACE4'), # Ultrsacale+
# Hard memory controllers.
Cell('MCB'), # Spartan 6 Memory Controller Block
Cell('HBM_REF_CLK', keep=True), # not in liraries guide
# not sure how the following relate to the hw
Cell('HBM_SNGLBLI_INTF_APB', keep=True), # not in liraries guide
Cell('HBM_SNGLBLI_INTF_AXI', keep=True), # not in liraries guide
Cell('HBM_ONE_STACK_INTF', keep=True), # not in liraries guide
Cell('HBM_TWO_STACK_INTF', keep=True), # not in liraries guide
# PowerPC.
# TODO PPC405 (Virtex 2)
Cell('PPC405_ADV'), # Virtex 4
Cell('PPC440'), # Virtex 5
# ARM.
Cell('PS7', keep=True), # The Zynq 7000 ARM Processor System (not in libraries guide).
Cell('PS8', keep=True), # The Zynq Ultrascale+ ARM Processor System (not in libraries guide).
# Misc hard IP.
Cell('ILKN'), # Ultrascale Interlaken
Cell('ILKNE4'), # Ultrascale+ Interlaken
Cell('VCU', keep=True), # Zynq MPSoC Video Codec Unit (not in libraries guide).
Cell('FE'), # Zynq RFSoC Forward Error Correction (not in libraries guide).
]
class State(Enum):
OUTSIDE = auto()
IN_MODULE = auto()
IN_OTHER_MODULE = auto()
IN_FUNCTION = auto()
IN_TASK = auto()
def xtract_cell_decl(cell, dirs, outf):
for dir in dirs:
for ext in ['.v', '.sv']:
fname = os.path.join(dir, cell.name + ext)
try:
with open(fname) as f:
state = State.OUTSIDE
found = False
# Probably the most horrible Verilog "parser" ever written.
module_ports = []
invertible_ports = set()
for l in f:
l = l.partition('//')[0]
l = l.strip()
if l == 'module {}'.format(cell.name) or l.startswith('module {} '.format(cell.name)):
if found:
print('Multiple modules in {}.'.format(fname))
sys.exit(1)
elif state != State.OUTSIDE:
print('Nested modules in {}.'.format(fname))
sys.exit(1)
found = True
state = State.IN_MODULE
if cell.keep:
outf.write('(* keep *)\n')
outf.write('module {} (...);\n'.format(cell.name))
elif l.startswith('module '):
if state != State.OUTSIDE:
print('Nested modules in {}.'.format(fname))
sys.exit(1)
state = State.IN_OTHER_MODULE
elif l.startswith('task '):
if state == State.IN_MODULE:
state = State.IN_TASK
elif l.startswith('function '):
if state == State.IN_MODULE:
state = State.IN_FUNCTION
elif l == 'endtask':
if state == State.IN_TASK:
state = State.IN_MODULE
elif l == 'endfunction':
if state == State.IN_FUNCTION:
state = State.IN_MODULE
elif l == 'endmodule':
if state == State.IN_MODULE:
for kind, rng, port in module_ports:
for attr in cell.port_attrs.get(port, []):
outf.write(' (* {} *)\n'.format(attr))
if port in invertible_ports:
outf.write(' (* invertible_pin = "IS_{}_INVERTED" *)\n'.format(port))
if rng is None:
outf.write(' {} {};\n'.format(kind, port))
else:
outf.write(' {} {} {};\n'.format(kind, rng, port))
outf.write(l + '\n')
outf.write('\n')
elif state != State.IN_OTHER_MODULE:
print('endmodule in weird place in {}.'.format(cell.name, fname))
sys.exit(1)
state = State.OUTSIDE
elif l.startswith(('input ', 'output ', 'inout ')) and state == State.IN_MODULE:
if l.endswith((';', ',')):
l = l[:-1]
if ';' in l:
print('Weird port line in {} [{}].'.format(fname, l))
sys.exit(1)
kind, _, ports = l.partition(' ')
for port in ports.split(','):
port = port.strip()
if port.startswith('['):
rng, port = port.split()
else:
rng = None
module_ports.append((kind, rng, port))
elif l.startswith('parameter ') and state == State.IN_MODULE:
if 'UNPLACED' in l:
continue
if l.endswith((';', ',')):
l = l[:-1]
while ' ' in l:
l = l.replace(' ', ' ')
if ';' in l:
print('Weird parameter line in {} [{}].'.format(fname, l))
sys.exit(1)
outf.write(' {};\n'.format(l))
match = re.search('IS_([a-zA-Z0-9_]+)_INVERTED', l)
if match:
invertible_ports.add(match[1])
if state != State.OUTSIDE:
print('endmodule not found in {}.'.format(fname))
sys.exit(1)
if not found:
print('Cannot find module {} in {}.'.format(cell.name, fname))
sys.exit(1)
return
except FileNotFoundError:
continue
print('Cannot find {}.'.format(cell.name))
sys.exit(1)
if __name__ == '__main__':
parser = ArgumentParser(description='Extract Xilinx blackbox cell definitions from ISE and Vivado.')
parser.add_argument('vivado_dir', nargs='?', default='/opt/Xilinx/Vivado/2018.1')
parser.add_argument('ise_dir', nargs='?', default='/opt/Xilinx/ISE/14.7')
args = parser.parse_args()
dirs = [
os.path.join(args.vivado_dir, 'data/verilog/src/xeclib'),
os.path.join(args.vivado_dir, 'data/verilog/src/unisims'),
os.path.join(args.vivado_dir, 'data/verilog/src/retarget'),
os.path.join(args.ise_dir, 'ISE_DS/ISE/verilog/xeclib/unisims'),
]
for dir in dirs:
if not os.path.isdir(dir):
print('{} is not a directory'.format(dir))
out = StringIO()
for cell in CELLS:
xtract_cell_decl(cell, dirs, out)
with open('cells_xtra.v', 'w') as f:
f.write('// Created by cells_xtra.py from Xilinx models\n')
f.write('\n')
f.write(out.getvalue())