def make_name(self, port): if isinstance(port, PortWrapper): port = port.select_path if isinstance(port, SelectPath): if len(port) > 2: name = f"dut.{port.system_verilog_path}" else: # Top level ports assign to the external reg name = verilog_name(port[-1].name) elif isinstance(port, fault.WrappedVerilogInternalPort): name = f"dut.{port.path}" else: name = verilog_name(port.name) return name
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});" ]
def make_poke(self, i, action): name = verilog_name(action.port.name) value = action.value width = get_width(action.port) # self.curr_state_pokes.append( # f"{name} = {value}_{width}") self.curr_state_pokes.append( f"self.{name} = {value}_{width}")
def make_poke(self, i, action): if isinstance(action.port, SelectPath): if len(action.port) > 2: name = f"dut.{action.port.system_verilog_path}" else: # Top level ports assign to the external reg name = verilog_name(action.port[-1].name) elif isinstance(action.port, fault.WrappedVerilogInternalPort): name = f"dut.{action.port.path}" else: name = verilog_name(action.port.name) # For now we assume that verilog can handle big ints value = action.value if 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"{name} = {value};", f"#{self.clock_step_delay}"]
def make_step(self, i, action): name = verilog_name(action.clock.name) code = [] for step in range(action.steps): code.append("top->eval();") code.append("main_time++;") code.append("#if VM_TRACE") code.append("tracer->dump(main_time);") code.append("#endif") code.append(f"top->{name} ^= 1;") return code
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}\");"]
def make_poke(self, i, action): if isinstance(action.port, SelectPath): name = f"dut.{action.port.system_verilog_path}" elif isinstance(action.port, fault.WrappedVerilogInternalPort): name = f"dut.{action.port.path}" else: name = verilog_name(action.port.name) if isinstance(action.value, BitVector) and \ action.value.num_bits > 32: raise NotImplementedError() else: value = action.value if 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"{name} = {value};", f"#{self.clock_step_delay}"]
def make_print(self, i, action): name = verilog_name(action.port.name) return [ f'printf("{action.port.debug_name} = ' f'{action.format_str}\\n", top->{name});' ]
def make_poke(self, i, action): 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}" elif isinstance(action.port, SelectPath): name = "" if len(action.port) > 2: # TODO: Find the version that they changed this, 3.874 is known # to use top->v instead of top->{circuit_name} name += f"{prefix}->" name += action.port.verilator_path if len(action.port) > 2: self.debug_includes.add(f"{action.port[0].circuit.name}") for item in action.port[1:-1]: circuit = type(item.instance) circuit_name = circuit.verilog_name # Verilator specializes each parametrization into a separate # mdoule, this is an attempt to reverse engineer the naming # scheme if circuit_name == "coreir_reg": circuit_name += "_" circuit_name += f"_I{circuit.coreir_configargs['init']}" circuit_name += f"_W{circuit.coreir_genargs['width']}" elif circuit_name == "coreir_reg_arst": circuit_name += "_" circuit_name += f"_I{circuit.coreir_configargs['init']}" if circuit.coreir_genargs['width'] != 1: circuit_name += f"_W{circuit.coreir_genargs['width']}" self.debug_includes.add(f"{circuit_name}") else: name = verilog_name(action.port.name) # Special case poking internal registers is_reg_poke = isinstance(action.port, SelectPath) and \ isinstance(action.port[-1], fault.WrappedVerilogInternalPort) \ and action.port[-1].path == "outReg" # max_bits = 64 if platform.architecture()[0] == "64bit" else 32 max_bits = 32 if isinstance(action.value, BitVector) and \ action.value.num_bits > max_bits: asserts = [] for i in range(math.ceil(action.value.num_bits / max_bits)): value = action.value[i * max_bits:min( (i + 1) * max_bits, action.value.num_bits)] asserts += [f"top->{name}[{i}] = {value};"] if is_reg_poke: raise NotImplementedError() return asserts else: value = action.value if isinstance(value, actions.FileRead): value = f"*{value.file.name_without_ext}_in" if 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() result = [f"top->{name} = {value};"] # Hack to support verilator's semantics, need to set the register # mux values for expected behavior if is_reg_poke: action.port[-1].path = "out" result += self.make_poke(i, action) action.port[-1].path = "in" result += self.make_poke(i, action) if "enable_mux" in action.port[-3].instance_map: mux_inst = action.port[-3].instance_map["enable_mux"] action.port[-2] = InstanceWrapper(mux_inst, action.port[-3]) action.port[-1] = type(mux_inst).I0 result += self.make_poke(i, action) return result
def make_step(self, i, action): name = verilog_name(action.clock.name) code = [] for step in range(action.steps): code.append(f"#5 {name} ^= 1;") return code
def make_print(self, i, action): name = verilog_name(action.port.name) return [ f'$display("{action.port.debug_name} = ' f'{action.format_str}", {name});' ]