Beispiel #1
0
 def visit_UnaryOp(self, node):
     """Visit Unary operations."""
     if isinstance(node.op, ast.Not):
         return HDLExpression(self.visit(node.operand)).bool_neg()
     elif isinstance(node.op, ast.Invert):
         return ~HDLExpression(self.visit(node.operand))
     else:
         raise TypeError("operator {} not supported".format(
             node.op.__class__.__name__))
Beispiel #2
0
def test_concat():
    """Test concatenation."""
    sig = HDLSignal("comb", "my_signal", size=4)
    concat = HDLConcatenation(sig, HDLExpression(0x0C, size=8))
    assert len(concat) == 12

    concat.append(HDLExpression(0x1, size=1))

    # failures
    with pytest.raises(TypeError):
        _ = HDLConcatenation(sig, "not_allowed")
Beispiel #3
0
    def visit_Compare(self, node):
        """Visit Compare."""
        self.generic_visit(node)
        if isinstance(node.left, ast.Name):
            # NOTE: Don't know why this is necessary anymore
            left_sig = self._signal_lookup(node.left.id)
            if left_sig is None:
                if self._signal_lookup(node.left.id) is not None:
                    # rename
                    node.left.id = "reg_" + str(node.left.id)
                else:
                    raise NameError('in "{}": signal "{}" not available in'
                                    " current scope".format(
                                        self._get_current_block(),
                                        node.left.id))
        if len(node.comparators) > 1:
            raise RuntimeError("only single comparison is allowed")
        (comp, ) = node.comparators
        if isinstance(comp, ast.Name):
            comp_sig = self._signal_lookup(comp.id)
            if comp_sig is None:
                if self._signal_lookup("reg_" + str(comp.id)) is not None:
                    # is state register, rename
                    comp.id = "reg_" + str(comp.id)
                else:
                    raise NameError('in "{}": signal "{}" not available in'
                                    " current scope".format(
                                        self._get_current_block(), comp.id))

        return HDLExpression(node)
Beispiel #4
0
def get_multiplexer(target, select, *options):
    """Generate multiplexer pattern."""
    if len(options) < 2:
        raise RuntimeError("must have 2 or more options")
    for idx, opt in enumerate(options):
        if not isinstance(opt, (HDLSignal, HDLSignalSlice, HDLModulePort)):
            raise RuntimeError(
                "options must be signals or ports, got: {}".format(type(opt))
            )
        if isinstance(opt, HDLModulePort):
            opt = opt.signal.name
        # None is placeholder for last expression
        if idx < len(options) - 1:
            _ifexp = HDLIfExp(HDLExpression(select == idx), opt, None)
        if idx == 0:
            ifexp = _ifexp
            root_ifexp = _ifexp
        else:
            # update last expression
            if idx == len(options) - 1:
                ifexp.else_value = opt
            else:
                ifexp.else_value = _ifexp
                ifexp = _ifexp

    return HDLAssignment(target, root_ifexp)
Beispiel #5
0
def test_hdl_module():
    """Test modules."""
    mod = HDLModule("my_module")
    mod = HDLModule("my_module", [HDLModulePort("in", "myport", 8)])
    mod = HDLModule("my_module",
                    params=[HDLModuleParameter("myparam", "integer", 0)])

    expr = ast.parse("myparam-1", mode="eval")
    vec = HDLVectorDescriptor(left_size=HDLExpression(expr), right_size=0)
    mod = HDLModule(
        "my_module",
        ports=[HDLModulePort("in", "myport", vec)],
        params=HDLModuleParameter("myparam", "integer", 0),
    )
    print(mod.dumps(evaluate=True))

    _ = mod.get_parameter_scope()
    _ = mod.get_full_scope()
    _ = mod.get_param_names()
    _ = mod.get_port_names()

    # failures
    with pytest.raises(TypeError):
        mod = HDLModule("my_module", 0)

    with pytest.raises(TypeError):
        mod = HDLModule("my_module", [0])

    with pytest.raises(TypeError):
        mod = HDLModule("my_module", params=[0])

    with pytest.raises(TypeError):
        mod = HDLModule("my_module", params=0)
Beispiel #6
0
def test_seq():
    """Test sequential block."""
    some_signal = HDLSignal("reg", "signal", size=1)
    sens_1 = HDLSensitivityDescriptor(sens_type="rise", sig=some_signal)

    sens_list = HDLSensitivityList()
    sens_list.add(sens_1)

    ass_sig = HDLSignal("reg", "counter", size=2)
    ass_expr = HDLExpression(ass_sig) + 1
    assign = HDLAssignment(ass_sig, ass_expr)

    seq = HDLSequentialBlock(sens_list)
    seq.add(assign)

    print(seq.dumps())
Beispiel #7
0
    def visit_If(self, node):
        """Visit If statement."""
        self.visit(node.test)
        ifelse = HDLIfElse(HDLExpression(ast.Expression(body=node.test)))
        self.current_scope.add([ifelse])
        last_scope = self.current_scope

        # ordered visit, two scopes, so separe
        self.current_scope = ifelse.if_scope
        for _node in node.body:
            self.visit(_node)
        self.current_scope = ifelse.else_scope
        for _node in node.orelse:
            self.visit(_node)
        self.current_scope = last_scope
        return node
Beispiel #8
0
def test_ifelse():
    """Test if-else."""
    # create an if-else block
    gen = VerilogCodeGenerator()

    sig = HDLSignal(sig_type="comb", sig_name="test", size=1)
    test_sig = HDLSignal(sig_type="reg", sig_name="counter", size=2)

    assign_rhs = HDLExpression(test_sig) + 1
    assignment = HDLAssignment(signal=test_sig, value=assign_rhs)

    ifelse = HDLIfElse(condition=sig)
    ifelse.add_to_if_scope(assignment)

    # make else
    assignment = HDLAssignment(signal=test_sig, value=0)
    ifelse.add_to_else_scope(assignment)

    print(gen.dump_element(ifelse))
Beispiel #9
0
 def visit_Name(self, node):
     """Visit Name."""
     signal = self._signal_lookup(node.id)
     if signal is not None:
         if isinstance(signal, HDLSignalSlice):
             signal_name = signal.signal.name
         elif isinstance(signal, (HDLSignal, HDLModulePort)):
             signal_name = signal.name
         elif isinstance(signal, int):
             signal_name = signal
         else:
             raise RuntimeError("unknown error")
     else:
         signal_name = node.id
     if self._verify_signal_name:
         if signal is None:
             raise NameError("unknown name: {}".format(node.id))
     node.id = signal_name
     return HDLExpression(signal_name)
Beispiel #10
0
def test_always():
    """Test always block."""
    gen = VerilogCodeGenerator()

    sig = HDLSignal(sig_type="reg", sig_name="clk", size=1)
    sens = HDLSensitivityDescriptor(sens_type="rise", sig=sig)
    sens_list = HDLSensitivityList()
    sens_list.add(sens)

    test_sig = HDLSignal(sig_type="reg", sig_name="counter", size=2)
    rst_assign = HDLAssignment(signal=test_sig, value=0)
    norm_expr = HDLExpression(test_sig) + 1
    norm_assign = HDLAssignment(signal=test_sig, value=norm_expr)

    rst = HDLSignal(sig_type="reg", sig_name="rst", size=1)
    ifelse = HDLIfElse(condition=rst)
    ifelse.add_to_if_scope(rst_assign)
    ifelse.add_to_else_scope(norm_assign)

    seq = HDLSequentialBlock(sensitivity_list=sens_list)
    seq.add(ifelse)

    print(gen.dump_element(seq))
Beispiel #11
0
    def visit_SlaveRegisterField(self, node):
        """Visit register field."""
        src_reg, src_field = node.source
        if src_reg not in self._registers:
            raise ValueError("unknown register: {}".format(src_reg))

        ssize = self.slice_size(self.bitfield_pos_to_slice(node.position))
        if node.default is not None:
            if isinstance(node.default, int):
                param_size = HDLIntegerConstant.minimum_value_size(
                    node.default
                )
                defval = node.default
            else:
                if node.default.strip() in self._parameters:
                    param_size = 0
                    defval = HDLExpression(node.default.strip(), size=ssize)
                else:
                    raise RuntimeError(
                        "unknown identifier: {}".format(node.default.strip())
                    )

            if ssize < param_size:
                raise RuntimeError("value does not fit in field")
        else:
            defval = 0

        reg_field = HDLRegisterField(
            src_field,
            self.bitfield_pos_to_slice(node.position),
            node.access,
            default_value=defval,
        )

        for prop in node.properties:
            reg_field.add_properties(**{prop.name: prop.value})
        self._registers[src_reg].add_fields(reg_field)
Beispiel #12
0
def test_hdl_expression():
    """Test expressions."""
    expr_1 = "PARAM-2"
    expr_2 = "PARAM_X+1"
    expr_3 = "a and ~b"
    hdl_expr_1 = HDLExpression(ast.parse(expr_1, mode="eval"))
    hdl_expr_2 = HDLExpression(ast.parse(expr_2, mode="eval"))
    hdl_expr_3 = HDLExpression(expr_3)
    print(hdl_expr_3.dumps())
    sum = hdl_expr_1 + hdl_expr_2
    neg = ~sum
    bool_neg = sum.bool_neg()
    bool_and = hdl_expr_1.bool_and(hdl_expr_2)
    bool_or = hdl_expr_1.bool_or(hdl_expr_2)
    print(sum.dumps())
    print(neg.dumps())
    print(bool_neg.dumps())
    print(bool_and.dumps())
    print(bool_or.dumps())

    _ = hdl_expr_1 & 0x1
    _ = 0x1 | hdl_expr_1
    _ = 0x1 & hdl_expr_1
    _ = 0x1 ^ hdl_expr_1
    _ = hdl_expr_1 ^ 0x1

    my_signal = HDLSignal("reg", "signal_a", size=2)
    _ = HDLExpression(HDLIntegerConstant(1))
    _ = HDLExpression(1)
    _ = HDLExpression(my_signal)
    _ = HDLExpression(HDLSignalSlice(my_signal, 1))
    _ = HDLExpression(my_signal[1:0])

    # test reduction
    expr_a = HDLExpression("value_a")
    expr_b = HDLExpression("value_b")
    full_expr = expr_a << 0 | expr_b << 16 | HDLExpression(0)

    case_1 = ast.BinOp(left=ast.Constant(value=0),
                       op=ast.BitOr(),
                       right=ast.Name(id="VAR"))

    case_2 = ast.BinOp(left=ast.Constant(value=1),
                       op=ast.Mult(),
                       right=ast.Name(id="VAR"))

    case_3 = ast.BinOp(left=ast.Constant(value=0),
                       op=ast.Mult(),
                       right=ast.Name(id="VAR"))

    hdl_expr = HDLExpression(ast.Expression(body=case_1))
    hdl_expr_2 = HDLExpression(ast.Expression(body=case_2))
    hdl_expr_3 = HDLExpression(ast.Expression(body=case_3))
    print(hdl_expr.dumps())
    print(hdl_expr_2.dumps())

    reduced_1 = HDLExpression._reduce_binop(case_1)
    hdl_expr = HDLExpression(ast.Expression(body=reduced_1))
    print(hdl_expr.dumps())

    reduced_2 = HDLExpression._reduce_binop(case_2)
    hdl_expr_2 = HDLExpression(ast.Expression(body=reduced_2))
    print(hdl_expr_2.dumps())

    reduced_3 = HDLExpression._reduce_binop(case_3)
    hdl_expr_3 = HDLExpression(ast.Expression(body=reduced_3))
    print(hdl_expr_3.dumps())

    print(full_expr.dumps())
    full_expr.reduce_expr()
    print(full_expr.dumps())
Beispiel #13
0
    def _parse_file(self):
        """Parse file."""
        meta_model = metamodel_from_file(
            pkg_resources.resource_filename(
                "hdltools", "verilog/module_grammar.tx"
            )
        )

        module_decl = meta_model.model_from_file(self.mod_file)

        # create module object
        hdl_mod = HDLModule(module_decl.mod_decl.mod_name)

        # create and add parameters
        if module_decl.mod_decl.param_decl is not None:
            params = module_decl.mod_decl.param_decl.params[:]
            for param in params:

                # use ast to parse
                if param.def_val.expr is not None:
                    param_str = param.def_val.expr.replace("$", "_")
                    param_tree = ast.parse(param_str, mode="eval")

                    # dependency check
                    param_deps = self._find_dependencies(param_tree)
                    for dep in param_deps:
                        if dep not in self.hdl_model.get_param_names():
                            raise KeyError(
                                "unknown identifier:" " {}".format(dep)
                            )

                    # evaluate parameters immediately (not necessary)
                    scope = hdl_mod.get_full_scope()
                    param_val = HDLExpression(param_tree).evaluate(**scope)
                else:
                    param_val = param.def_val.bitstr

                hdl_param = HDLModuleParameter(
                    param_name=param.par_name,
                    param_type=param.par_type,
                    param_default=param_val,
                )

                hdl_mod.add_parameters(hdl_param)

        self.hdl_model = hdl_mod

        # create and add ports
        ports = module_decl.mod_decl.ports[:]
        for port in ports:
            # ugly, but not my fault
            direction = self._class_to_port_dir[port.__class__.__name__]
            name = port.decl.port_name
            if port.decl.srange is not None:
                size = (
                    port.decl.srange.left_size,
                    port.decl.srange.right_size,
                )

                # use ast to parse, avoiding complicated grammar
                left_str = port.decl.srange.left_size.replace("$", "_")
                right_str = port.decl.srange.right_size.replace("$", "_")
                left_tree = ast.parse(left_str, mode="eval")
                right_tree = ast.parse(right_str, mode="eval")
                left_deps = self._find_dependencies(left_tree)
                right_deps = self._find_dependencies(right_tree)

                # search dependencies in parameters
                for dep in left_deps:
                    if dep not in self.hdl_model.get_param_names():
                        raise KeyError("unknown identifier: {}".format(dep))
                for dep in right_deps:
                    if dep not in self.hdl_model.get_param_names():
                        raise KeyError("unknown identifier: {}".format(dep))

                size = (HDLExpression(left_tree), HDLExpression(right_tree))
            else:
                size = (0, 0)
            try:
                hdl_port = HDLModulePort(
                    direction=direction, name=name, size=size
                )
            except TypeError:
                pass

            self.hdl_model.add_ports(hdl_port)
Beispiel #14
0
 def __pos__(self):
     """Access internal signal as an expression."""
     return HDLExpression(self.signal)
Beispiel #15
0
 def visit_BinOp(self, node):
     """Visit Binary operations."""
     self.generic_visit(node)
     return HDLExpression(ast.Expression(body=node))
Beispiel #16
0
    def visit_Assign(self, node):
        """Visit Assignments."""
        self.generic_visit(node)
        assignments = []
        # check assignees (targets)
        assignees = []
        for target in node.targets:
            if isinstance(target, ast.Attribute):
                # attributes are not allowed, except for self access
                if target.value.id == "self":
                    # bypass attribute access directly,
                    # later on we can execute the block itself in python
                    # if necessary
                    target.id = target.attr
                else:
                    raise PatternNotAllowedError(
                        "Attribute access is not allowed in HDL blocks.")
            if self._signal_lookup(target.id) is None:
                if self._signal_lookup("reg_" + target.id) is None:
                    raise NameError('in "{}": signal "{}" not available in'
                                    " current scope".format(
                                        self._get_current_block(), target.id))
                else:
                    target.id = "reg_" + target.id
            assignees.append(target.id)

        # check value assigned
        if isinstance(node.value, ast.Name):
            if self._signal_lookup(node.value.id) is None:
                raise NameError('in "{}": signal "{}" not available in'
                                " current scope".format(
                                    self._get_current_block(), node.value.id))
            for assignee in assignees:
                assignments.append(
                    HDLAssignment(
                        self._signal_lookup(assignee),
                        self._signal_lookup(node.value.id),
                    ))
        elif isinstance(node.value, ast.Constant):
            for assignee in assignees:
                assignments.append(
                    HDLAssignment(
                        self._signal_lookup(assignee),
                        HDLExpression(node.value.value),
                    ))
        elif isinstance(node.value, (ast.List, ast.Tuple)):
            items = [self.visit(item) for item in node.value.elts]
            for assignee in assignees:
                assignments.append(
                    HDLAssignment(
                        self._signal_lookup(assignee),
                        HDLConcatenation(*items[::-1]),
                    ))
        elif isinstance(node.value, ast.Call):
            for assignee in assignees:
                args = [self._signal_lookup(arg.id) for arg in node.value.args]
                kwargs = {
                    kw.arg: self._signal_lookup(kw.value.id)
                    for kw in node.value.keywords
                }
                if node.value.func.id in self._symbols:
                    fn = self._symbols[node.value.func.id]
                    # generate
                    ret = fn(*args, **kwargs)
                else:
                    # dont do anything for now, lazy
                    fn = node.value.func.id
                    ret = (HDLLazyValue(
                        fn,
                        fnargs=args,
                        fnkwargs=kwargs,
                    ), )
                assignments.append(
                    HDLAssignment(self._signal_lookup(assignee), ret))
        else:
            try:
                expr = self.visit(node.value)
                for assignee in assignees:
                    assignments.append(
                        HDLAssignment(self._signal_lookup(assignee), expr))
            except TypeError:
                # raise TypeError('type {} not supported'.format(
                #    node.value.__class__.__name__))
                raise
        # find out where to insert statement
        if len(assignments) > 0:
            self.current_scope.add(*assignments)
Beispiel #17
0
 def visit_Constant(self, node):
     """Visit Constant."""
     if isinstance(node.value, int):
         return HDLExpression(node.value)
     return node