blob: f7eee406f475c308ecc73ffb2bf2588898efe0b8 (
plain) (
tree)
|
|
# Code to parse Verilog's integer constant syntax so that we can
# generate C headers from Verilog constants.
#
# Doesn't attempt to handle the analogue states ("x", "z", "?").
#
# Reference: http://verilog.renerta.com/source/vrg00020.htm
class VerilogInteger(object):
radix = dict(b = 2, o = 8, d = 10, h = 16)
def __init__(self, input):
head, sep, tail = input.lower().translate(None, " \t_").partition("'")
self.input = input
self.code = tail[0] if tail else None
if not sep:
self.width = 32
self.value = int(head)
elif self.code in self.radix:
self.width = int(head) if head else 32
self.value = int(tail[1:], self.radix[self.code])
if self.width <= 0 or self.value < 0:
raise ValueError
else:
raise ValueError
if self.width is not None:
mask = (1L << self.width) - 1
if self.value > mask:
self.value &= mask
elif self.value < -mask:
self.value = -( -self.value & mask)
@property
def C(self):
if self.code is None:
return str(self.value)
elif self.code == "d":
return "{0:d}".format(self.value)
elif self.code == "o":
return "0{0:0{1}o}".format(self.value, (self.width + 2) / 3)
else:
return "0x{0:0{1}x}".format(self.value, (self.width + 3) / 4)
@property
def Verilog(self):
if self.code is None:
return str(self.value)
else:
fmt = "x" if self.code == "h" else self.code
return "{0.width}'{0.code}{0.value:{1}}".format(self, fmt)
if __name__ == "__main__":
def show(*args):
print("{:20} | {:20} | {:20}".format(*args))
show("C", "Verilog", "Input")
show("-" * 20, "-" * 20, "-" * 20)
def test(x):
v = VerilogInteger(x)
show(v.C, v.Verilog, v.input)
test("15")
test("'h f")
test("'o 17")
test("'d 15")
test("'b 1111")
test("'b 1_1_1_1")
test("10 'd 20")
test("6'o 71")
test("8'b0")
test("8'b00000000")
test("8'b1")
test("8'b00000001")
try:
for line in open("/tmp/sample-verilog-numbers"):
test(line.strip())
except IOError:
pass
|