aboutsummaryrefslogblamecommitdiff
path: root/verilog-integer.py
blob: f7eee406f475c308ecc73ffb2bf2588898efe0b8 (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                                












































                                                                              



                          
                    
                                                    

























                                                        
# 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