mirror of https://github.com/XS-MLVP/picker.git
229 lines
7.3 KiB
Python
229 lines
7.3 KiB
Python
#coding=utf8
|
|
{% if __SIMULATOR__ == "vcs" %}
|
|
import os
|
|
import sys
|
|
|
|
|
|
def _check_vcs_static_tls_capacity():
|
|
if sys.platform != "linux":
|
|
return
|
|
|
|
tunable_name = "glibc.rtld.optional_static_tls"
|
|
required_size = 65536
|
|
|
|
tunables = os.environ.get("GLIBC_TUNABLES", "")
|
|
for item in (item for item in tunables.split(":") if item):
|
|
if item.startswith(f"{tunable_name}="):
|
|
try:
|
|
if int(item.split("=", 1)[1]) >= required_size:
|
|
return
|
|
except ValueError:
|
|
break
|
|
|
|
raise RuntimeError(
|
|
"VCS Python packages require glibc optional static TLS space. "
|
|
f"Please run Python with GLIBC_TUNABLES={tunable_name}={required_size}. "
|
|
"For example: "
|
|
f"GLIBC_TUNABLES={tunable_name}={required_size} python example.py. "
|
|
"Increase the GLIBC_TUNABLES value if multiple VCS DUT packages are "
|
|
"loaded in the same Python process."
|
|
)
|
|
|
|
|
|
_check_vcs_static_tls_capacity()
|
|
{% endif %}
|
|
|
|
try:
|
|
from . import xspcomm as xsp
|
|
except Exception as e:
|
|
import xspcomm as xsp
|
|
|
|
if __package__ or "." in __name__:
|
|
from .libUT_{{__TOP_MODULE_NAME__}} import *
|
|
else:
|
|
from libUT_{{__TOP_MODULE_NAME__}} import *
|
|
|
|
|
|
class DUT{{__TOP_MODULE_NAME__}}(object):
|
|
|
|
# initialize
|
|
def __init__(self, *args, **kwargs):
|
|
self.dut = DutUnifiedBase(*args)
|
|
self.xclock = xsp.XClock(self.dut.pxcStep, self.dut.pSelf)
|
|
self.xport = xsp.XPort()
|
|
self.xclock.Add(self.xport)
|
|
self.event = self.xclock.getEvent()
|
|
self.internal_signals = {}
|
|
self.xcfg = xsp.XSignalCFG(self.dut.GetXSignalCFGPath(), self.dut.GetXSignalCFGBasePtr())
|
|
{% if __SIMULATOR__ == "gsim" %}
|
|
# Set fast mode for GSim
|
|
self.xclock.SetFastMode(xsp.FastMode_ONLY_STEP_RIS)
|
|
{% endif %}
|
|
|
|
# set output files
|
|
if kwargs.get("waveform_filename"):
|
|
self.dut.SetWaveform(kwargs.get("waveform_filename"))
|
|
if kwargs.get("coverage_filename"):
|
|
self.dut.SetCoverage(kwargs.get("coverage_filename"))
|
|
|
|
# All pins
|
|
{{__XDATA_INIT__}}
|
|
|
|
# BindDPI or Native pin address
|
|
{{__XDATA_BIND__}}
|
|
|
|
# Add2Port
|
|
{{__XPORT_ADD__}}
|
|
|
|
# Cascaded ports
|
|
{{__XPORT_CASCADED__}}
|
|
|
|
def __del__(self):
|
|
self.Finish()
|
|
|
|
################################
|
|
# User APIs #
|
|
################################
|
|
def InitClock(self, name: str):
|
|
self.xclock.Add(self.xport[name])
|
|
|
|
def Step(self, i:int = 1):
|
|
self.xclock.Step(i)
|
|
|
|
def StepRis(self, callback, args=(), kwargs={}):
|
|
self.xclock.StepRis(callback, args, kwargs)
|
|
|
|
def StepFal(self, callback, args=(), kwargs={}):
|
|
self.xclock.StepFal(callback, args, kwargs)
|
|
|
|
def ResumeWaveformDump(self):
|
|
return self.dut.ResumeWaveformDump()
|
|
|
|
def PauseWaveformDump(self):
|
|
return self.dut.PauseWaveformDump()
|
|
|
|
def WaveformPaused(self) -> int:
|
|
""" Returns 1 if waveform export is paused """
|
|
return self.dut.WaveformPaused()
|
|
|
|
def GetXPort(self):
|
|
return self.xport
|
|
|
|
def GetXClock(self):
|
|
return self.xclock
|
|
|
|
def SetWaveform(self, filename: str):
|
|
self.dut.SetWaveform(filename)
|
|
|
|
def GetWaveFormat(self) -> str:
|
|
"""
|
|
Get the waveform extension, or an empty string if disabled.
|
|
|
|
Returns:
|
|
str: The extension of waveform file.
|
|
"""
|
|
return self.dut.GetWaveFormat()
|
|
|
|
def FlushWaveform(self):
|
|
self.dut.FlushWaveform()
|
|
|
|
def SetCoverage(self, filename: str):
|
|
self.dut.SetCoverage(filename)
|
|
|
|
def GetCovMetrics(self) -> int:
|
|
"""
|
|
Get the bitmask for collected coverage metrics. 0 means coverage is disabled
|
|
|
|
Returns:
|
|
int: Collected coverage metrics bitmask:
|
|
- Bit 0: line (Line coverage)
|
|
- Bit 1: cond (Condition coverage)
|
|
- Bit 2: fsm (Finite-State Machine coverage)
|
|
- Bit 3: toggle (Toggle coverage)
|
|
- Bit 4: branch (Branch coverage)
|
|
- Bit 5: assert (Assertion coverage)
|
|
"""
|
|
return self.dut.GetCovMetrics()
|
|
|
|
def CheckPoint(self, name: str) -> int:
|
|
self.dut.CheckPoint(name)
|
|
|
|
def Restore(self, name: str) -> int:
|
|
self.dut.Restore(name)
|
|
|
|
def GetInternalSignal(self, name: str, index=-1, is_array=False, use_vpi=False):
|
|
if name not in self.internal_signals:
|
|
signal = None
|
|
if self.dut.GetXSignalCFGBasePtr() != 0 and not use_vpi:
|
|
xname = "CFG:" + name
|
|
if is_array:
|
|
assert index < 0, "Index is not supported for array signal"
|
|
signal = self.xcfg.NewXDataArray(name, xname)
|
|
elif index >= 0:
|
|
signal = self.xcfg.NewXData(name, index, xname)
|
|
else:
|
|
signal = self.xcfg.NewXData(name, xname)
|
|
else:
|
|
assert index < 0, "Index is not supported for VPI signal"
|
|
assert not is_array, "Array is not supported for VPI signal"
|
|
signal = xsp.XData.FromVPI(self.dut.GetVPIHandleObj(name),
|
|
self.dut.GetVPIFuncPtr("vpi_get"),
|
|
self.dut.GetVPIFuncPtr("vpi_get_value"),
|
|
self.dut.GetVPIFuncPtr("vpi_put_value"), "VPI:" + name)
|
|
if use_vpi:
|
|
assert signal is not None, f"Internal signal {name} not found (Check VPI is enabled)"
|
|
if signal is None:
|
|
return None
|
|
if not isinstance(signal, xsp.XData):
|
|
self.internal_signals[name] = [xsp.XPin(s, self.event) for s in signal]
|
|
else:
|
|
self.internal_signals[name] = xsp.XPin(signal, self.event)
|
|
return self.internal_signals[name]
|
|
|
|
def GetInternalSignalList(self, prefix="", deep=99, use_vpi=False):
|
|
if self.dut.GetXSignalCFGBasePtr() != 0 and not use_vpi:
|
|
return self.xcfg.GetSignalNames(prefix)
|
|
else:
|
|
return self.dut.VPIInternalSignalList(prefix, deep)
|
|
|
|
def VPIInternalSignalList(self, prefix="", deep=99):
|
|
return self.dut.VPIInternalSignalList(prefix, deep)
|
|
|
|
def Finish(self):
|
|
self.dut.Finish()
|
|
|
|
def RefreshComb(self):
|
|
self.dut.RefreshComb()
|
|
|
|
def AtClone(self):
|
|
"""Re-init simulator state in child after fork."""
|
|
return self.dut.atClone()
|
|
|
|
################################
|
|
# End of User APIs #
|
|
################################
|
|
|
|
def __getitem__(self, key):
|
|
return xsp.XPin(self.port[key], self.event)
|
|
|
|
# Async APIs wrapped from XClock
|
|
async def AStep(self,i: int):
|
|
return await self.xclock.AStep(i)
|
|
|
|
async def ACondition(self,fc_cheker):
|
|
return await self.xclock.ACondition(fc_cheker)
|
|
|
|
def RunStep(self,i: int):
|
|
return self.xclock.RunStep(i)
|
|
|
|
def __setattr__(self, name, value):
|
|
assert not isinstance(getattr(self, name, None),
|
|
(xsp.XPin, xsp.XData)), \
|
|
f"XPin and XData of DUT are read-only, do you mean to set the value of the signal? please use `{name}.value = ` instead."
|
|
return super().__setattr__(name, value)
|
|
|
|
|
|
if __name__=="__main__":
|
|
dut=DUT{{__TOP_MODULE_NAME__}}()
|
|
dut.Step(100)
|