blob: 9dc339b17844725f84e3aae5c0b623381c3ac3d9 [file]
import lxml.etree as ET
from enum import Enum
def clog2(x):
"""Ceiling log 2 of x.
>>> clog2(0), clog2(1), clog2(2), clog2(3), clog2(4)
(0, 0, 1, 2, 2)
>>> clog2(5), clog2(6), clog2(7), clog2(8), clog2(9)
(3, 3, 3, 3, 4)
>>> clog2(1 << 31)
31
>>> clog2(1 << 63)
63
>>> clog2(1 << 11)
11
"""
x -= 1
i = 0
while True:
if x <= 0:
break
x = x >> 1
i += 1
return i
class MuxType(Enum):
LOGIC = 'BEL_MX'
ROUTING = 'BEL_RX'
class MuxPinType(Enum):
INPUT = 'i'
SELECT = 's'
OUTPUT = 'o'
def verilog(self):
if self in (self.INPUT, self.SELECT):
return "input wire"
elif self == self.OUTPUT:
return "output wire"
else:
raise TypeError("Can't convert {} into verilog definition.".format(self))
def direction(self):
if self in (self.INPUT, self.SELECT):
return "input"
elif self == self.OUTPUT:
return "output"
else:
raise TypeError("Can't convert {} into verilog definition.".format(self))
def __str__(self):
return self.value
def pb_type_xml(mux_type, mux_name, pins, subckt=None, num_pb=1, comment=""):
"""Generate <pb_type> XML for a mux.
Parameters
----------
mux_type: MuxType
Type of mux to create.
mux_name: str
Name of the mux.
pins: [(MuxPinType, str, int, int),]
List of tuples which contain (pin type, pin name, port width, index)
subckt: str
Name of the blif_model for the mux. Only valid when mux_type ==
MuxType.LOGIC.
num_pb: int
Value for the num_pb value. Defaults to 1.
comment: str
Optional comment for the mux.
Returns
-------
xml.etree.ElementTree
pb_type.xml for requested mux
"""
assert isinstance(comment, str), "{} {}".format(type(comment), repr(comment))
if mux_type == MuxType.LOGIC:
if '-' not in mux_name:
mux_name = 'BEL_MX-'+mux_name
else:
assert mux_name.startswith('BEL_MX-'), "Provided mux name has type {} but not BEL_MX!".format(mux_name)
elif mux_type == MuxType.ROUTING:
if '-' not in mux_name:
mux_name = 'BEL_RX-'+mux_name
else:
assert mux_name.startswith('BEL_RX-'), "Provided mux name has type {} but not BEL_MX!".format(mux_name)
else:
assert False, "Unknown type {}".format(mux_type)
pb_type_xml = ET.Element(
'pb_type', {
'name': mux_name,
'num_pb': str(num_pb),
})
if mux_type == MuxType.LOGIC:
pb_type_xml.attrib['blif_model'] = '.subckt %s' % subckt
else:
assert not subckt, "Provided subckt={} for non-logic mux!".format(subckt)
if comment is not None:
pb_type_xml.append(ET.Comment(comment))
for pin_type, pin_name, pin_width, pin_index in pins:
#assert pin_index < pin_width, (
# "Pin index {} >= width {} for pin {} {}".format(pin_index, pin_width, pin_name, pin_type))
if mux_type == MuxType.ROUTING and pin_type == MuxPinType.SELECT:
continue
ET.SubElement(
pb_type_xml,
pin_type.direction(),
{'name': pin_name, 'num_pins': str(pin_width)},
)
if mux_type == MuxType.LOGIC:
for ipin_type, ipin_name, ipin_width, ipin_index in pins:
if ipin_type not in (MuxPinType.INPUT, MuxPinType.SELECT):
continue
for opin_type, opin_name, opin_width, opin_index in pins:
if opin_type not in (MuxPinType.OUTPUT,):
continue
ET.SubElement(
pb_type_xml,
'delay_constant', {
'max': "10e-12",
'in_port': "%s.%s" % (mux_name, ipin_name),
'out_port': "%s.%s" % (mux_name, opin_name),
},
)
elif mux_type == MuxType.ROUTING:
interconnect = ET.SubElement(pb_type_xml, 'interconnect')
inputs = ["{}.{}".format(mux_name, n) for t, n, _, _ in pins if t in (MuxPinType.INPUT,)]
outputs = ["{}.{}".format(mux_name, n) for t, n, _, _ in pins if t in (MuxPinType.OUTPUT,)]
assert len(outputs) == 1
ET.SubElement(
interconnect,
'mux', {
'name': '%s' % (mux_name,),
'input': " ".join(inputs),
'output': outputs[0],
},
)
return pb_type_xml
if __name__ == "__main__":
import doctest
doctest.testmod()