aboutsummaryrefslogtreecommitdiff
path: root/verilog-integer.py
diff options
context:
space:
mode:
Diffstat (limited to 'verilog-integer.py')
-rw-r--r--verilog-integer.py86
1 files changed, 86 insertions, 0 deletions
diff --git a/verilog-integer.py b/verilog-integer.py
new file mode 100644
index 0000000..e9a1ba5
--- /dev/null
+++ b/verilog-integer.py
@@ -0,0 +1,86 @@
+# 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