Ejemplo n.º 1
0
    def make_expect(self, i, action):
        if value_utils.is_any(action.value):
            return []
        if isinstance(action.port, SelectPath):
            name = f"dut.{action.port.system_verilog_path}"
            debug_name = action.port[-1].name
        elif isinstance(action.port, fault.WrappedVerilogInternalPort):
            name = f"dut.{action.port.path}"
            debug_name = name
        else:
            name = verilog_name(action.port.name)
            debug_name = action.port.name
        value = action.value
        if isinstance(value, actions.Peek):
            if isinstance(value.port, fault.WrappedVerilogInternalPort):
                value = f"dut.{value.port.path}"
            else:
                value = f"{value.port.name}"
        elif isinstance(value, PortWrapper):
            value = f"dut.{value.select_path.system_verilog_path}"
        elif isinstance(action.port, m.SIntType) and value < 0:
            # Handle sign extension for verilator since it expects and
            # unsigned c type
            port_len = len(action.port)
            value = BitVector(value, port_len).as_uint()

        return [
            f"if ({name} != {value}) $error(\"Failed on action={i}"
            f" checking port {debug_name}. Expected %x, got %x\""
            f", {value}, {name});"
        ]
Ejemplo n.º 2
0
    def make_expect(self, i, action):
        # For verilator, if an expect is "AnyValue" we don't need to
        # perform the expect.
        if value_utils.is_any(action.value):
            return []
        prefix = self.get_verilator_prefix()
        if isinstance(action.port, fault.WrappedVerilogInternalPort):
            path = action.port.path.replace(".", "->")
            name = f"{prefix}->{path}"
            debug_name = name
        elif isinstance(action.port, SelectPath):
            name = action.port.verilator_path
            if len(action.port) > 2:
                name = f"{prefix}->" + name
            debug_name = action.port[-1].debug_name
        else:
            name = verilator_name(action.port.name)
            debug_name = action.port.debug_name
        value = action.value
        if isinstance(value, actions.Peek):
            value = self.process_peek(value)
        elif isinstance(value, PortWrapper):
            value = f"top->{prefix}->" + value.select_path.verilator_path
        if isinstance(action.value, BitVector) and \
                action.value.num_bits > max_bits:
            asserts = []
            # For some reason, verilator chunks it by 32 instead of max_bits
            slice_range = 32
            for j in range(math.ceil(action.value.num_bits / slice_range)):
                value = action.value[j * slice_range:min(
                    (j + 1) * slice_range, action.value.num_bits)]
                asserts += [
                    f"my_assert(top->{name}[{j}], {value}, "
                    f"{i}, \"{debug_name}\");"
                ]
            return asserts
        else:
            value = self.process_value(action.port, value)
            port_value = f"top->{name}"
            port_value = self.process_bitwise_expect(action.port, port_value)

            port = action.port
            if isinstance(port, SelectPath):
                port = port[-1]
            elif isinstance(port, fault.WrappedVerilogInternalPort):
                port = port.type_
            if isinstance(port, m.Digital):
                port_len = 1
            else:
                port_len = len(port)
            mask = (1 << port_len) - 1

            return [
                f"my_assert({port_value}, {value} & {mask}, "
                f"{i}, \"{debug_name}\");"
            ]
Ejemplo n.º 3
0
    def make_expect(self, i, action):
        # don't do anything if any value is OK
        if value_utils.is_any(action.value):
            return []

        # determine the exact name of the signal
        name = self.make_name(action.port)

        # TODO: add something like "make_read_name" and "make_write_name"
        # so that reading inout signals has more uniform behavior across
        # expect, peek, etc.
        if actions.is_inout(action.port):
            name = self.input_wire(name)

        # determine the name of the signal for debugging purposes
        if isinstance(action.port, SelectPath):
            debug_name = action.port[-1].name
        elif isinstance(action.port, fault.WrappedVerilogInternalPort):
            debug_name = name
        else:
            debug_name = action.port.name

        # determine the value to be checked
        value = self.process_value(action.port, action.value)

        # determine the condition and error body
        err_body = f'"Failed on action={i} checking port {debug_name}.'
        if action.above is not None:
            if action.below is not None:
                # must be in range
                cond = f'({action.above} <= {name}) && ({name} <= {action.below})'  # noqa
                err_body += f' Expected %0f to %0f, got %0f", {action.above}, {action.below}, {name}'  # noqa
            else:
                # must be above
                cond = f'{action.above} <= {name}'
                err_body += f' Expected above %0f, got %0f", {action.above}, {name}'  # noqa
        else:
            if action.below is not None:
                # must be below
                cond = f'{name} <= {action.below}'
                err_body += f' Expected below %0f, got %0f", {action.below}, {name}'  # noqa
            else:
                # equality comparison
                if action.strict:
                    cond = f'{name} === {value}'
                else:
                    cond = f'{name} == {value}'
                err_body += f' Expected %x, got %x" , {value}, {name}'

        # return a snippet of verilog implementing the assertion
        retval = []
        retval += [f'if (!({cond})) begin']
        retval += [self.make_line(f'$error({err_body});', tabs=1)]
        retval += ['end']
        return retval
Ejemplo n.º 4
0
    def make_expect(self, i, action):
        # For verilator, if an expect is "AnyValue" we don't need to
        # perform the expect.
        if value_utils.is_any(action.value):
            return []
        if self.verilator_version > 3.874:
            prefix = f"{self.circuit_name}"
        else:
            prefix = f"v"
        if isinstance(action.port, fault.WrappedVerilogInternalPort):
            path = action.port.path.replace(".", "->")
            name = f"{prefix}->{path}"
            debug_name = name
        elif isinstance(action.port, SelectPath):
            name = action.port.verilator_path
            if len(action.port) > 2:
                name = f"{prefix}->" + name
            if self.verilator_version >= 3.856:
                if len(action.port) > 2:
                    self.debug_includes.add(f"{action.port[0].circuit.name}")
            for item in action.port[1:-1]:
                circuit_name = type(item.instance).name
                self.debug_includes.add(f"{circuit_name}")
            debug_name = action.port[-1].debug_name
        else:
            name = verilog_name(action.port.name)
            debug_name = action.port.debug_name
        value = action.value
        if isinstance(value, actions.Peek):
            if isinstance(value.port, fault.WrappedVerilogInternalPort):
                path = action.port.path.replace(".", "->")
                value = f"top->{prefix}->{path}"
            else:
                value = f"top->{verilog_name(value.port.name)}"
        elif isinstance(value, PortWrapper):
            if self.verilator_version >= 3.856:
                if len(action.port) > 2:
                    self.debug_includes.add(f"{action.port[0].circuit.name}")
            for item in value.select_path[1:-1]:
                circuit_name = type(item.instance).name
                self.debug_includes.add(f"{circuit_name}")
            value = f"top->{prefix}->" + value.select_path.verilator_path
        elif isinstance(action.port, m.SIntType) and value < 0:
            # Handle sign extension for verilator since it expects and
            # unsigned c type
            port_len = len(action.port)
            value = BitVector(value, port_len).as_uint()

        return [f"my_assert(top->{name}, {value}, " f"{i}, \"{debug_name}\");"]
Ejemplo n.º 5
0
    def make_expect(self, i, action):
        # For verilator, if an expect is "AnyValue" we don't need to
        # perform the expect.
        if value_utils.is_any(action.value):
            return []
        prefix = self.get_verilator_prefix()
        if isinstance(action.port, fault.WrappedVerilogInternalPort):
            path = action.port.path.replace(".", "->")
            name = f"{prefix}->{path}"
            debug_name = name
        elif isinstance(action.port, SelectPath):
            name = action.port.verilator_path
            if len(action.port) > 2:
                name = f"{prefix}->" + name
            debug_name = action.port[-1].debug_name
        else:
            name = verilator_name(action.port.name)
            debug_name = action.port.debug_name
        value = action.value
        if isinstance(value, actions.Peek):
            value = self.process_peek(value)
        elif isinstance(value, PortWrapper):
            value = f"top->{prefix}->" + value.select_path.verilator_path

        user_msg = ()
        if action.msg is not None:
            if isinstance(action.msg, str):
                user_msg += (action.msg, )
            else:
                assert isinstance(action.msg, tuple)
                user_msg += (action.msg[0], )
                user_msg += self._make_print_args(action.msg[1:])

        if isinstance(action.value, BitVector) and \
                action.value.num_bits > max_bits:
            asserts = []
            # For some reason, verilator chunks it by 32 instead of max_bits
            slice_range = 32
            for j in range(math.ceil(action.value.num_bits / slice_range)):
                value = action.value[j * slice_range:min(
                    (j + 1) * slice_range, action.value.num_bits)]
                asserts.append(
                    self._make_assert(f"((unsigned int) top->{name}[{j}])",
                                      f"((unsigned int) {value})", i,
                                      f"\"{debug_name}\"", user_msg))
            return asserts
        else:
            value = self.process_value(action.port, value)
            port_value = f"top->{name}"
            port_value = self.process_bitwise_expect(action.port, port_value)

            port = action.port
            if isinstance(port, SelectPath):
                port = port[-1]
            elif isinstance(port, fault.WrappedVerilogInternalPort):
                port = port.type_
            if isinstance(port, m.Digital):
                port_len = 1
            else:
                port_len = len(port)

            # deal with real-valued expressions
            if isinstance(port, RealType):
                got = f"({port_value})"
                expected = f"({value})"
                style = 'scientific'
            else:
                mask = (1 << port_len) - 1
                got = f"((unsigned int) {port_value})"
                expected = f"(unsigned int) ({value} & {mask})"
                style = 'hex'

            return [
                self._make_assert(got=got,
                                  expected=expected,
                                  i=i,
                                  port=f'"{debug_name}"',
                                  user_msg=user_msg,
                                  below=action.below,
                                  above=action.above,
                                  style=style)
            ]
Ejemplo n.º 6
0
    def make_expect(self, i, action):
        # don't do anything if any value is OK
        if value_utils.is_any(action.value):
            return []

        # determine the exact name of the signal
        name = self.make_name(action.port)

        # TODO: add something like "make_read_name" and "make_write_name"
        # so that reading inout signals has more uniform behavior across
        # expect, peek, etc.
        if actions.is_inout(action.port):
            name = self.input_wire(name)

        # determine the name of the signal for debugging purposes
        if isinstance(action.port, SelectPath):
            debug_name = action.port[-1].name
        elif isinstance(action.port, fault.WrappedVerilogInternalPort):
            debug_name = name
        else:
            debug_name = action.port.name

        # determine the value to be checked
        value = self.process_value(action.port, action.value)

        # determine the condition and error body
        err_hdr = ''
        err_hdr += f'Failed on action={i} checking port {debug_name}'
        if action.traceback is not None:
            err_hdr += f' with traceback {action.traceback}'
        if action.above is not None:
            if action.below is not None:
                # must be in range
                cond = f'(({action.above} <= {name}) && ({name} <= {action.below}))'  # noqa
                err_msg = 'Expected %0f to %0f, got %0f'
                err_args = [action.above, action.below, name]
            else:
                # must be above
                cond = f'({action.above} <= {name})'
                err_msg = 'Expected above %0f, got %0f'
                err_args = [action.above, name]
        else:
            if action.below is not None:
                # must be below
                cond = f'({name} <= {action.below})'
                err_msg = 'Expected below %0f, got %0f'
                err_args = [action.below, name]
            else:
                # equality comparison
                if action.strict:
                    cond = f'({name} === {value})'
                else:
                    cond = f'({name} == {value})'
                err_msg = 'Expected %x, got %x'
                err_args = [value, name]
        if action.msg is not None:
            if isinstance(action.msg, str):
                err_msg += "\\n" + action.msg
            else:
                assert isinstance(action.msg, tuple)
                err_msg += "\\n" + action.msg[0]
                err_args += self._make_print_args(action.msg[1:])

        # construct the body of the $error call
        err_fmt_str = f'"{err_hdr}.  {err_msg}."'
        err_body = [err_fmt_str] + err_args
        err_body = ', '.join([str(elem) for elem in err_body])

        if self.use_sva:
            return [f'assert ({cond}) else $error({err_body});']
        else:
            # return a snippet of verilog implementing the assertion
            return self.make_if(i, If(f'!{cond}', [f'$error({err_body});']))