SPV Enable:
Python HDL Verification
Python as other language have advantages and disadvantages.
New: Using python as a verification environment.
We add in SPV a package that support using python as a verification environment. A special python package supplied with interface to HDL include the following python classes:
-
Signal access READ/WRITE.
-
Create HDL event and enable Wait(HdlEvent),
-
Scheduler that enable:
-
create python thread (TCM).
-
Manage all thread in simulation time.
-
-
Global method that enable:
-
Advance time.
-
pass to simulator prompt and return.
-
Print or use time as a variable.
-
-
All python capabilities free for any using in the verification environment.
Example:
In this example we drive packet to design, while the Monitor/Checker check correction. There are 4 interfaces each Driver/Monitor instance take care of 1 interface.
The following function display:
-
Driver function -- Drive NumPacket that configured by Python random
-
Monitor function -- Monitor data and check correction, mutual score board fill by driver, while monitor collect data and make compare.
-
Generator - Generate interface and NumPacket.
-
Test - Launch Monitor and Driver for NumPacket driving and checking.
Driver code
# Driver code drive 'NumFrame=X' packets
# import scheduler and HDL python interface
from SpvPython import *
# import python signal interface to the HDL itself
from AllSig import *
# import random to generate numPackeet .
import random
# import current Generator that generate the HDL interface.
from Generator import *
def DriveProc(id: int):
newVal = 0;#value to set to m_SigData
#There are 4 interface get current HDL interface
MiiInf = MiiInterface(id);
# Create event
clkPos = SPSigEvent(MiiInf.SigClk,AtPos);
#example how to declare signal access local.
SigData= SPSig(TOP_0 + "miiD" + str(id));
MiiInf.SigEn.Set(0);#Set data to HDL
StrPrefix = "Driver" + str(id) + ":";
#Loop that send NumFrame packets
for FrameIndex in range (0,NumFrame):
GlobSched.WaitEv(clkPos); #Wait clk
for SliceInd in range(0,99):
if SliceInd is 0:
MiiInf.SigEn.Set(1);
#Set enable when start new frame
else
MiiInf.SigErr.Set(0);
#drive random data using pythom random
newVal=(int(random.random()*0x7FFFFFFF))%256;
SigData.Set(newVal);
#Prepare the expected formonitor MiiInf.listData.append(newVal+6); GlobSched.WaitEv(clkPos);
#before new loop set enable '0'
MiiInf.SigEn.Set(0);
#wait 1-10 clocks
numWait=(int(random.random()*0x7FFFFFFF)%10) +4;
#Wait some clocks before next packet
for i in range (0,numWait): GlobSched.WaitEv(clkPos);
Monitor code
# Monitor code drive 'NumFrame=X' packets
# import scheduler and HDL python interface
from SpvPython import *
# import python signal interface to the HDL itself
from AllSig import *
# import random to generate numPackeet .
import random
# import current Generator that generate the HDL interface.
from Generator import *
# import Entry SPV which is the SPV interface to python.
import SPV
def MonitorProc(id: int):
getVal = 0;
PacketInd = 0;
#Get interface [0..3] with the score board pointer
MiiInf = MiiInterface(id);
# create event on clock posedge
clkPos =SPSigEvent(MiiInf.SigClk,AtPos);
SigData =SPSig(TOP_0+"miiD"+str(id)); #example how to declare local signal interface
DataValidPos=SPSigEvent(MiiInf.SigEn,AtPos)
StrPrefix = "Monitor" + str(id) + ":";
while True:
SliceInd = 0;
if MiiInf.SigEn.Val64() is 0:
GlobSched.WaitEv(DataValidPos);
#wait 1 clock any way
GlobSched.WaitEv(clkPos);
while MiiInf.SigEn.Val64() is 1:
Time = "T: " + str(SPV.SimTime());
getVal = SigData.Val64();
if (len(MiiInf.listData) >0):
if (MiiInf.listData[0] != getVal):
print(StrPrefix," Error** in pkt ",PacketInd,"derive:",MiiInf.listData[0]," Got ",getVal,Time);
else:
print (StrPrefix, " OK in packet ",PacketInd,"Slice ",SliceInd," is ",getVal,"T: ",Time);
#throw frame after finish check
MiiInf.listData.pop(0);
GlobSched.WaitEv(clkPos);
SliceInd = SliceInd + 1;
PacketInd= PacketInd +1;
if PacketInd >= NumFrame:
GlobSched.WaitEv(clkPos);
return;
Generator code
# Generator code , generate the interface and score board
import random
from AllSig import *
# score board for interface 0..3
listOfData0 = [];
listOfData1 = [];
listOfData2 = [];
listOfData3 = [];
NumFrame = 3; # default
def GenNumFrame(max: int):
NumFrame=(int(random.random()*0x7FFFFFFF)% max)+1;
class MiiInterface():
def __init__(self,miiInd: int):
self.strId=str(miiInd);
#initial clk[0..3] by dynamic string
self.SigClk=SPSig(TOP_0+"mii_clk"+miiInd);
# enable[0..3]
self.SigEn=SPSig(TOP_0+"mii_en"+miiInd);
#err[0..3]
self.SigErr=SPSig(TOP_0+"mii_err"+miiInd);
exec("self.listData=listOfData%d"%miiInd));
# create string on line
Test Code
# Start Driver and monitor code as a thread, they start immediately.
import Driver
import Monitor
def Test():
#create driver + monitor interface 0
GlobSched.AddThread(Driver.DriveProc,'Dr0',0)
GlobSched.AddThread(Monitor.MonitorProc,'Mon0',0)
# Run SpvPython scheduler, start all the TCM as a HDL thread
GlobSched.Run();
HDL Interface
#This list of signal created automatically by SPV HDL explorer.
#when such line declare, it immediately connected to design
from SpvPython import *;
#Path list
TOP_0 = "topTb." # the full path string
m_Sigclk_in = SPSig( TOP_0 + "clk_in");
m_Sigmain_rst = SPSig( TOP_0 + "main_rst");
m_Sigclk0 = SPSig( TOP_0 + "clk0");
m_SigdataIn0 = SPSig( TOP_0 + "dataIn0");
m_SigdataOut0 = SPSig( TOP_0 + "dataOut0");
m_Sigclk1 = SPSig( TOP_0 + "clk1");
m_SigdataIn1 = SPSig( TOP_0 + "dataIn1");
m_SigdataOut1 = SPSig( TOP_0 + "dataOut1");
m_Sigclk2 = SPSig( TOP_0 + "clk2");
m_SigdataIn2 = SPSig( TOP_0 + "dataIn2");
m_SigdataOut2 = SPSig( TOP_0 + "dataOut2");
m_Sigmii_clk0 = SPSig( TOP_0 + "mii_clk0");
m_SigmiiD0 = SPSig( TOP_0 + "miiD0");
m_Sigmii_en0 = SPSig( TOP_0 + "mii_en0");
m_Sigmii_err0 = SPSig( TOP_0 + "mii_err0");
m_Sigmii_clkPy = SPSig( TOP_0 + "mii_clkPy");
m_SigmiiDPy = SPSig( TOP_0 + "miiDPy");
m_Sigmii_enPy = SPSig( TOP_0 + "mii_enPy");
m_Sigmii_errPy = SPSig( TOP_0 + "mii_errPy");
m_Sigmii_clk1 = SPSig( TOP_0 + "mii_clk1");