top of page

SPV Test-bench Studio, represents a further step forward in verification technology. It is a software environment, integrated with RTL hardware simulation environment.SPV integrates with VHDL/Verilog/Mix for Linux/Windows, designed for writing verification test suites.

SPV is a verification environment, which takes the advantages of the strongest tools and languages, imports them, in order to help building rich and faster verification environment.    

SPV enable write mix languages, C++, C, Python and MATLAB for writing verification code. 

 

Tools:

  • Verification frame work for editing, compiling, linking and debugging.

    • Visual studio for windows.

    • Eclipse for Linux

    • MATLAB become to be C interface by using MCC compiler, and DPF os SimPlus.

  • Advantages:​

    • The most powerful and flexible editing tools, that enable the same environment to compile link and debug the code.

    • GUI environment for testing process:

      • Change test parametrs, Generators, clocks, Boolean, numbers (float, double, Uint, Int, Long vectoor), and even creating processes that drive and check the design by mouse click only.

    • C ++ is a language that is supported and developed by millions of engineers worldwide, providing detailed documentation, examples and explanations of what a user might think. These engineers have developed the language to be the most rich, providing a solution to every problem. Many libraries for almost any purpose, and an open and rich language that allows the final developer to do whatever he likes, using the best tools for developing, running and debugging.

    • Standard - C ++ is the most stable and standard language. Old C code (30 years ago),  works excelent, with the newest methods available today, platforms and environment 

    • the most of the abilities no cost.

    File SpvMain.cpp:

 

1.    Special function that should be exists, called from SPV kernel at time 0, when simulation loaded, and create the testbench tree.

2.    option - explore design and prepare interface (For C++ and python) in true condition. 

3.    GUI - Read GUI data base, generators, Boolean, signals, strings and more 

4.    make new 2 Boot-Strap that hold the testbench tree.    

#include "SpvHfile.h"
#include "BootStrap.h"
#include "AllSig.h"

void    SpvMain(int argc, char** argv)//SpvMain called first from kernel simulator
{       
   cout << "Run SPV Version 7 dll" << endl;
   if (false) {        
       vector<string>  pathList;
       pathList.push_back("TopCalc");        
       SpvConfig::CreateSpvHdlInf(pathList, "./Runtime", ExpAllType);
       cout << " HDL interface for SimDesignTop1 created, Please compile again spv.v" << endl;
       StopSim();
       return;
   }
   //Load GUI  data base    
   SD::LoadRunTime("./Runtime");
   if (SD::IsExists("USE_ASSERT", BoolType))
       SpvConfig::SetAssert(SD::GetBool("USE_ASSERT"));
   else
       SpvConfig::SetAssert(false);
   SpvConfig::SetInternalErrorType((SpvInternalError)(SD::GetUint("STOP_SIMULATION")));
   SpvConfig::UseSeed((SpvSeedType)(SD::GetUint("RAND_SEED")), SD::GetUint("SEED"));
   SpvConfig::SetCoutImmediat(true);
   

    //Start the test bench
   PrepareGSpvCharAttr();
   SH::InitStaticSignal();
   BootStrap* test = new BootStrap;    
}

    File BootStrap.{h,cpp}:

 

1.    Create the testbench tree - and start run after 10 NS.

//BootStrap.h

#pragma once
#include "Driver.h"


class    BootStrap : public SpvBase
{
public:
    BootStrap();    
    void        StartProcess();
    Driver*     m_Driver;        
};

//BootStrap.cpp

 

#include "BootStrap.h"
#include "AllSig.h"

SpvSig  m_Rst;

BootStrap::BootStrap()
{
    m_Driver = NULL;
    StartTProc(this, (SpvProcMethod)&BootStrap::StartProcess);
    SH::m_Siguse_SpvTb = 1;
}

void    BootStrap::StartProcess()
{    
    Wait(10);
    m_Driver = new Driver();
    m_Driver->StartProcess();
}

SPV_ADVANTAGES

​​

    File Driver.{h,cpp}:

1.    In this file we declare events, Pos/Neg for each clock.

2    we declare TCM (Time consuming method) function of 2 types:

a.    Thread function (with wait in the middle of function) - easy use but little slowly.

b.    Atomic process - called each simulator event - Very fast code, but sometimes not convinces. 

3.    we declare variable to hold the expected results for each Verilog module.

​​​

//Driver.h

​​

#pragma once
#include "SpvHfile.h"
#include "ParseHelper.h"


class    Driver : public SpvBase
{
public:
    Driver();
    SpvEvent    m_ClkOrPos      , m_ClkOrNeg;//15
    SpvEvent    m_ClkAddPos     , m_ClkAddNeg;//20
    SpvEvent    m_ClkSubPos     , m_ClkSubNeg;//25
    SpvEvent    m_ClkMultPos    , m_ClkMultNeg;//30
    SpvEvent    m_ClkAndPos     , m_ClkAndNeg;//35
    SpvEvent    m_ClkModePos    , m_ClkModeNeg;//40
    SpvEvent    m_ClkXorPos     , m_ClkXorNeg;//45
    SpvEvent    m_ClkShiftLPos  , m_ClkShiftLNeg;//50
    SpvEvent    m_ClkShiftRPos  , m_ClkShiftRNeg;//55
    SpvEvent    m_ClkCurledPos  , m_ClkCurledNeg;//500
    void    StartProcess();

    //Calculator process
    void        DoAlwaysOr();
    void        DoAlwaysAdd();
    void        DoAlwaysSub();
    void        DoAlwaysMult();
    void        DoAlwaysAnd();
    void        DoAlwaysMode();
    void        DoAlwaysXor();
    void        DoAlwaysShiftL();
    void        DoAlwaysShiftR();
    
    void        DriveCheckAlwaysOrTP();
    void        DriveCheckAlwaysAddTP();
    void        DriveCheckAlwaysSubTP();      
    void        DriveCheckAlwaysMultTP();
    void        DriveCheckAlwaysAndTP();
    void        DriveCheckAlwaysModeTP();
    void        DriveCheckAlwaysXorTP();    
    void        DriveCheckAlwaysShiftLTP();
    void        DriveCheckAlwaysShiftRTP();
    void        DriveCruledAlwaysTP();

    void        DriveCheckAlwaysOrFast();
    void        DriveCheckAlwaysAddFast();
    void        DriveCheckAlwaysSubFast();
    void        DriveCheckAlwaysMultFast();
    void        DriveCheckAlwaysAndFast();
    void        DriveCheckAlwaysModeFast();
    void        DriveCheckAlwaysXorFast();    
    void        DriveCheckAlwaysShiftLFast();
    void        DriveCheckAlwaysShiftRFast();
    void        DriveCruledAlwaysFast();

    unsigned   m_OrA    , m_OrB     , m_OrRes;
    unsigned   m_AddA   , m_AddB    , m_AddRes;
    unsigned   m_SubA   , m_SubB    , m_SubRes;
    unsigned   m_MultA  , m_MultB   , m_MultRes;
    unsigned   m_AndA   , m_AndB    , m_AndRes;
    unsigned   m_ModeA  , m_ModeB   , m_ModeRes;
    unsigned   m_XorA   , m_XorB    , m_XorRes;    
    unsigned   m_ShiftLA, m_ShiftLB , m_ShiftLRes;
    unsigned   m_ShiftRA, m_ShiftRB , m_ShiftRRes;

    unsigned    m_OrNumErr      , m_OrNumOK;
    unsigned    m_AddNumErr     , m_AddNumOK;
    unsigned    m_SubNumErr     , m_SubNumOK;
    unsigned    m_MultNumErr    , m_MultNumOK;
    unsigned    m_AndNumErr     , m_AndNumOK;
    unsigned    m_ModeNumErr    , m_ModeNumOK;
    unsigned    m_XorNumErr     , m_XorNumOK;    
    unsigned    m_ShiftLNumErr  , m_ShiftLNumOK;
    unsigned    m_ShiftRNumErr  , m_ShiftRNumOK;
    unsigned    m_CruledNumErr  , m_CruledNumOK;

    //Curled
    SpvBitVec   m_RegAVec, m_RegBVec, m_RegCVec, m_RegDVec;
    Literal     m_Literal8Bit;
    unsigned    m_ConstCurled;
    SpvBitVec   m_CurledA, m_CurledB, m_ExpWireA, m_ExpWireB, m_ExpWireC;
};

​​​

     Driver.cpp 

#include "AllSig.h"
#include "Driver.h"


unsigned loopSize;
Driver::Driver()
{    

   //Init signals and event
   m_ClkOrNeg.Init(SH::m_Sigclk_or, AtNeg);//15
   m_ClkAddNeg.Init(SH::m_Sigclk_add, AtNeg);//20
   m_ClkSubNeg.Init(SH::m_Sigclk_sub, AtNeg);//25
   m_ClkMultNeg.Init(SH::m_Sigclk_mult, AtNeg);//30
   m_ClkAndNeg.Init(SH::m_Sigclk_and, AtNeg);//35
   m_ClkModeNeg.Init(SH::m_Sigclk_mode, AtNeg);//40
   m_ClkXorNeg.Init(SH::m_Sigclk_xor, AtNeg);//45
   m_ClkShiftLNeg.Init(SH::m_Sigclk_shiftL, AtNeg);//50
   m_ClkShiftRNeg.Init(SH::m_Sigclk_shiftR, AtNeg);//55
   m_ClkCurledNeg.Init(SH::m_Sigcurled_clk, AtNeg);//55        

    m_ClkOrPos.Init(SH::m_Sigclk_or, AtNeg);//20
   m_ClkAddPos.Init(SH::m_Sigclk_add, AtPos);//20
   m_ClkSubPos.Init(SH::m_Sigclk_sub, AtPos);//25
   m_ClkMultPos.Init(SH::m_Sigclk_mult, AtPos);//30
   m_ClkAndPos.Init(SH::m_Sigclk_and, AtPos);//35
   m_ClkModePos.Init(SH::m_Sigclk_mode, AtPos);//40
   m_ClkXorPos.Init(SH::m_Sigclk_xor, AtPos);//45
   m_ClkShiftLPos.Init(SH::m_Sigclk_shiftL, AtPos);//50
   m_ClkShiftRPos.Init(SH::m_Sigclk_shiftR, AtPos);//55
   m_ClkCurledPos.Init(SH::m_Sigcurled_clk, AtPos);//55  

   //Init num error and num OK to be 0     

    m_XorNumErr        = 0;
   m_OrNumErr        = 0;
   m_AndNumErr        = 0;
   m_MultNumErr    = 0;
   m_AddNumErr        = 0;
   m_SubNumErr        = 0;
   m_ShiftLNumErr    = 0;
   m_ShiftRNumErr    = 0;
   m_CruledNumErr  = 0;
   m_XorNumOK        = 0;
   m_OrNumOK        = 0;
   m_AndNumOK        = 0;
   m_MultNumOK        = 0;
   m_AddNumOK        = 0;
   m_SubNumOK        = 0;
   m_ShiftLNumOK    = 0;
   m_ShiftRNumOK    = 0;
   m_CruledNumOK    = 0;
   loopSize        = SD::GetUint("LOOP_SIZE");
   cout << "LoopSize ==" << loopSize << endl;

   //Init SpvBitVec size to be as signals size
   m_ExpWireA.Resize(SH::m_SigwireA.Size());
   m_ExpWireB.Resize(SH::m_SigwireB.Size());
   m_ExpWireC.Resize(SH::m_SigwireC.Size());
   m_RegAVec.Resize(SH::m_SigregA.Size());
   m_RegBVec.Resize(SH::m_SigregB.Size());
   m_RegCVec.Resize(SH::m_SigregC.Size());
   m_RegDVec.Resize(SH::m_SigregD.Size());

   //Init const literal value by string 
   m_Literal8Bit.Init("8'b1100XxZz");

   //init cruly variable size
   m_ConstCurled = 0xAbCdEf01;    
   m_CurledA.Resize(64);
   m_CurledB.Resize(64);
   //Set literal value in correct bit as a slice.    
   unsigned firstLiteralCurledBit = SH::m_SigregD.Size() + SH::m_SigregC.Size() + SH::m_SigregB.Size();
   unsigned secondLiteralCurledBit=firstLiteralCurledBit+m_Literal8Bit.m_Avec.Size()-1;
    
    m_CurledA(firstLiteralCurledBit,secondLiteralCurledBit) = m_Literal8Bit.m_Avec;
   m_CurledB(firstLiteralCurledBit, secondLiteralCurledBit) = m_Literal8Bit.m_Bvec;
   m_CurledA(secondLiteralCurledBit + 1, secondLiteralCurledBit + 32) = m_ConstCurled;
   m_CurledB(secondLiteralCurledBit + 1, secondLiteralCurledBit + 32) = 0;
   //assign{ wireA,wireB,wireC } = { regA,0xAbCdEf01,8'b1100XxZz,regB,regC,regD[0:2],regD[3]};
}

void    Driver::StartProcess()
{                
   if (SD::GetBool("DO_FAST_PROC")) {
//Start all fast process if DO_FAST_PROC == true
       //4M actions time performance:      Debug: 8 second. Release: 2.5 second.        
       cout << " DO_FAST_PROC=TRUE Mode loopSize = " << loopSize << endl;
       StartAProc(m_ClkOrNeg,this, (SpvProcMethod)&Driver::DriveCheckAlwaysOrFast);
       StartAProc(m_ClkAddNeg,this, (SpvProcMethod)&Driver::DriveCheckAlwaysAddFast);
       StartAProc(m_ClkSubNeg,this, (SpvProcMethod)&Driver::DriveCheckAlwaysSubFast);
       StartAProc(m_ClkMultNeg,this,(SpvProcMethod)&Driver::DriveCheckAlwaysMultFast);
       StartAProc(m_ClkAndNeg,this, (SpvProcMethod)&Driver::DriveCheckAlwaysAndFast);
       StartAProc(m_ClkModeNeg,this,(SpvProcMethod)&Driver::DriveCheckAlwaysModeFast);
       StartAProc(m_ClkXorNeg,this, (SpvProcMethod)&Driver::DriveCheckAlwaysXorFast);
       StartAProc(m_ClkShiftLNeg,this, (SpvProcMethod)&Driver::DriveCheckAlwaysShiftLFast);
       StartAProc(m_ClkShiftRNeg,    this, (SpvProcMethod)&Driver::DriveCheckAlwaysShiftRFast);
       StartAProc(m_ClkCurledNeg,    this, (SpvProcMethod)&Driver::DriveCruledAlwaysFast);

    }    else {//Start all thread process if DO_FAST_PROC == false
       //0.4M actions time performance:      Debug: 37 second. Release: 29 second.        
       cout << " DO_FAST_PROC=FALSE Mode loopSize = " << loopSize << endl;
       StartTProc(this, (SpvProcMethod)&Driver::DriveCheckAlwaysOrTP);
       StartTProc(this, (SpvProcMethod)&Driver::DriveCheckAlwaysAddTP);
       StartTProc(this, (SpvProcMethod)&Driver::DriveCheckAlwaysSubTP);
       StartTProc(this, (SpvProcMethod)&Driver::DriveCheckAlwaysMultTP);
       StartTProc(this, (SpvProcMethod)&Driver::DriveCheckAlwaysAndTP);
       StartTProc(this, (SpvProcMethod)&Driver::DriveCheckAlwaysModeTP);
       StartTProc(this, (SpvProcMethod)&Driver::DriveCheckAlwaysXorTP);        
       StartTProc(this, (SpvProcMethod)&Driver::DriveCheckAlwaysShiftLTP);
       StartTProc(this, (SpvProcMethod)&Driver::DriveCheckAlwaysShiftRTP);
       StartTProc(this, (SpvProcMethod)&Driver::DriveCruledAlwaysTP);
   }
}

///////////////////////////////////////////////////   OR /////////////////////

void        Driver::DriveCheckAlwaysOrTP()
{
   for (unsigned i = 0; i < loopSize; i++) {
       if (i) {
           Wait(m_ClkOrNeg);
           if (m_OrRes != SH::m_Sigor_res) {
               cout <<i<<": Error ***: m_OrA = 0x" <<hex<<m_OrA << " m_OrB = 0x .."<<endl;
               m_OrNumErr++;
           } else {
               m_OrNumOK++;
           }
       }
       m_OrA = GenUnsigned(); m_OrB = GenUnsigned(); m_OrRes = m_OrA | m_OrB;
       SH::m_Sigor_a = m_OrA; SH::m_Sigor_b = m_OrB;
   }
   cout <<"DriveCheckAlwaysOrTP m_OrNumErr="<<m_OrNumErr<<" m_OrNumOK="<<m_OrNumOK<< endl;
}

void     Driver::DriveCheckAlwaysOrFast()
{
   static unsigned cnt = 0;    
   if (cnt++) {
       if (m_OrRes != SH::m_Sigor_res) {
           cout <<cnt<<": Error ***: m_OrA=0x"<<hex<<m_OrA<<" m_OrB = 0x"<<endl;

           m_OrNumErr++;
       } else {
           m_OrNumOK++;
       }
   }
   
//Set data and calculate expected for next negedge.
   m_OrA = GenUnsigned(); m_OrB = GenUnsigned(); m_OrRes = m_OrA | m_OrB;
   SH::m_Sigor_a = m_OrA; SH::m_Sigor_b = m_OrB;
   if (cnt > loopSize) {
       CurrAProc()->Kill();
       cout << "DriveCheckAlwaysOr m_OrNumErr=" << m_OrNumErr << " m_OrNumOK = ";

       cout << m_OrNumOK << endl;
   }
}

///////////////////////////////////////////////////   ADD //////////////////////

void        Driver::DriveCheckAlwaysAddTP()
{
   for (unsigned i = 0; i < loopSize; i++) {
       if (i) {
           Wait(m_ClkAddNeg);
           if (m_AddRes != SH::m_Sigadd_res) {   
               cout<<i<<": Error ***: m_AddA = 0x"<<hex <<m_AddA<<" m_AddB = 0x.."<<endl;
               m_AddNumErr++;
           } else {
               m_AddNumOK++;
           }
       }
       m_AddA = GenUnsigned(); m_AddB = GenUnsigned(); m_AddRes = m_AddA + m_AddB;
       SH::m_Sigadd_a = m_AddA; SH::m_Sigadd_b = m_AddB;
   }
   cout<<"DriveCheckAlwaysAddTP m_AddNoErr="<<m_AddNoErr<<" m_AddNoOK="<<m_AddNumOK<<endl;
}

void        Driver::DriveCheckAlwaysAddFast()
{
   static unsigned cnt = 0;
   if (cnt++) {
       if (m_AddRes != SH::m_Sigadd_res) {
           cout<<cnt<<": Error ***: m_AddA=0x"<<hex<<m_AddA<<" m_AddB=0x"<< m_AddB<<endl;
           m_AddNumErr++;
       } else {
           m_AddNumOK++;
       }
   }

   //Set data Add calculate expected for next negedge.
   m_AddA = GenUnsigned(); m_AddB = GenUnsigned(); m_AddRes = m_AddA + m_AddB;
   SH::m_Sigadd_a = m_AddA; SH::m_Sigadd_b = m_AddB;
   if (cnt > loopSize) {
       CurrAProc()->Kill();
       cout<<"DriveCheckAlwaysAdd NoErr="<< m_AddNumErr<<" NoOK="<<m_AddNumOK <<endl;
   }
}

///////////////////////////////////////////////////   SUB //////////////////

void        Driver::DriveCheckAlwaysSubTP()
{
   for (unsigned i = 0; i < loopSize; i++) {
       if (i) {
           Wait(m_ClkSubNeg);
           if (m_SubRes != SH::m_Sigsub_res) {               
               cout<<i<<": Error ***:m_SubA=0x"<<hex<<m_SubA<<" m_SubB=0x"<<m_SubB<<endl;
               m_SubNumErr++;
           } else {
               m_SubNumOK++;
           }
       }

        m_SubA = GenUnsigned(); m_SubB = GenUnsigned(); m_SubRes = m_SubA - m_SubB;
       SH::m_Sigsub_a = m_SubA; SH::m_Sigsub_b = m_SubB;
   }
   cout<<"DriveCheckAlwaysSubTP NoErr="<<m_SubNumErr<<" NoOK = "<<m_SubNumOK << endl;
}

void        Driver::DriveCheckAlwaysSubFast()
{
   static unsigned cnt = 0;
   if (cnt++) {
       if (m_SubRes != SH::m_Sigsub_res) {
           cout<<cnt<<": Error ***: m_SubA=0x"<<hex<<m_SubA<<" m_SubB=0x"<<m_SubB<<endl;
           m_SubNumErr++;
       } else {
           m_SubNumOK++;
       }
   }

   //Set data Sub calculate expected for next negedge.
   m_SubA = GenUnsigned(); m_SubB = GenUnsigned(); m_SubRes = m_SubA - m_SubB;
   SH::m_Sigsub_a = m_SubA; SH::m_Sigsub_b = m_SubB;
   if (cnt > loopSize) {
       CurrAProc()->Kill();
       cout<<"DriveCheckAlwaysSubFast NoErr="<<m_SubNumErr <<" NoOK="<< m_SubNumOK << endl;
   }
}

//////////////////////////////////////////////   MULT /////////////////////////////

void        Driver::DriveCheckAlwaysMultTP()
{
   for (unsigned i = 0; i < loopSize; i++) {
       if (i) {
           Wait(m_ClkMultNeg);
           if (m_MultRes != SH::m_Sigmult_res) {               
               cout<<i<<": Error ***: m_MultA = 0x"<<hex<<m_MultA<<" m_MultB = 0x"<<endl;
               m_MultNumErr++;
           }  else {
               m_MultNumOK++;
           }
       }
       m_MultA = GenUnsigned(); m_MultB = GenUnsigned(); m_MultRes = m_MultA * m_MultB;
       SH::m_Sigmult_a = m_MultA; SH::m_Sigmult_b = m_MultB;
   }
   cout<<"DriveCheckAlwaysMultTP NoErr="<<m_MultNumErr<<" NoOK="<< m_MultNumOK<<endl;
}

void       Driver::DriveCheckAlwaysMultFast()
{
   static unsigned cnt = 0;
   if (cnt++) {
       if (m_MultRes != SH::m_Sigmult_res) {
           cout << cnt << ": Error ***: m_MultA = 0x" << hex << m_MultA << " m_MultB = 0x" << m_MultB << " SPV result = 0x" << m_MultRes << " HDL m_Sigmult_res = " << SH::m_Sigmult_res(SpvHex) << dec << " T:" << SimTime() << endl;
           m_MultNumErr++;
       }
       else {
           m_MultNumOK++;
       }
   }
   //Set data Mult calculate expected for next negedge.
   m_MultA = GenUnsigned(); m_MultB = GenUnsigned(); m_MultRes = m_MultA * m_MultB;
   SH::m_Sigmult_a = m_MultA; SH::m_Sigmult_b = m_MultB;
   if (cnt > loopSize) {
       CurrAProc()->Kill();
       cout << "DriveCheckAlwaysMultFast m_MultNumErr=" << m_MultNumErr << " m_MultNumOK = " << m_MultNumOK << endl;
   }
}

/////////////////////////////   AND ///////////////////

void        Driver::DriveCheckAlwaysAndTP()
{
   for (unsigned i = 0; i < loopSize; i++) {
       if (i) {
           Wait(m_ClkAndNeg);
           if (m_AndRes != SH::m_Sigand_res) {               
               cout<<i<<": Error ***: m_AndA=0x"<<hex<<m_AndA<<" m_AndB=0x"<<m_AndB<<endl;
               m_AndNumErr++;
           } else {
               m_AndNumOK++;
           }
       }
       m_AndA = GenUnsigned(); m_AndB = GenUnsigned(); m_AndRes = m_AndA & m_AndB;
       SH::m_Sigand_a = m_AndA; SH::m_Sigand_b = m_AndB;

    }
   cout<<"DriveCheckAlwaysAndTP NoErr=" << m_AndNumErr << " NoOK = " << m_AndNumOK << endl;
}

void        Driver::DriveCheckAlwaysAndFast()
{
   static unsigned cnt = 0;
   if (cnt++) {
       if (m_AndRes != SH::m_Sigand_res) {
           cout<<cnt<<": Error ***: m_AndA=0x"<<hex<<m_AndA<<" m_AndB=0x"<<m_AndB<<endl;
           m_AndNumErr++;
       } else {
           m_AndNumOK++;
       }
   }

   //Set data and calculate expected for next negedge.
   m_AndA = GenUnsigned(); m_AndB = GenUnsigned(); m_AndRes = m_AndA & m_AndB;
   SH::m_Sigand_a = m_AndA; SH::m_Sigand_b = m_AndB;
   if (cnt > loopSize) {
       CurrAProc()->Kill();
       cout<<"DriveCheckAlwaysAndFast NoErr="<<m_AndNumErr <<" NoOK="<< m_AndNumOK<<endl;
   }
}

///////////////////////////////////////////////////   MODE //////////////////////////


void        Driver::DriveCheckAlwaysModeTP()
{
   for (unsigned i = 0; i < loopSize; i++) {
       if (i) {
           Wait(m_ClkModeNeg);
           if (m_ModeRes != SH::m_Sigmode_res) {
               cout<<i<<": Error ***: m_ModeA = 0x"<<hex<<m_ModeA<< " m_ModeB = 0x"<<endl;
               m_ModeNumErr++;
           } else {
               m_ModeNumOK++;
           }
       }
       m_ModeA = GenUnsigned(0, 0x7FFFFFFF); m_ModeB = GenUnsigned(0, 0x7FFFFFFF);                 m_ModeRes = m_ModeA % m_ModeB;
       SH::m_Sigmode_a = m_ModeA; SH::m_Sigmode_b = m_ModeB;

    }
   cout<<"DriveCheckAlwaysModeTP NoErr="<< m_ModeNumErr << " NoOK="<<m_ModeNumOK<<endl;
}

void        Driver::DriveCheckAlwaysModeFast()
{
   static unsigned cnt = 0;
   if (cnt++) {
       if (m_ModeRes != SH::m_Sigmode_res) {
           cout<<cnt<<": Error ***:m_ModeA=0x"<<hex<<m_ModeA<<" m_ModeB=0x"<<m_ModeB<<endl;
           m_ModeNumErr++;
       } else {
           m_ModeNumOK++;
       }
   }
   
//Set data and calculate expected for next negedge.
   m_ModeA            = GenUnsigned(0, 0x7FFFFFFF); m_ModeB = GenUnsigned(0, 0x7FFFFFFF);     m_ModeRes = m_ModeA % m_ModeB;
   SH::m_Sigmode_a = m_ModeA; SH::m_Sigmode_b = m_ModeB;
   if (cnt > loopSize) {
       CurrAProc()->Kill();
       cout<<"DriveCheckAlwaysModeFast NoErr="<<m_ModeNumErr<<" NoOK="<<m_ModeNumOK <<endl;
   }
}

///////////////////////////////////////////////////   XOR ///////////////////////

void        Driver::DriveCheckAlwaysXorTP()
{    
   for (unsigned i = 0; i < loopSize; i++) {
       if (i) {
           Wait(m_ClkXorNeg);
           if (m_XorRes != SH::m_Sigxor_res) {
               cout<<i<<": Error ***: m_XorA=0x"<<hex<<m_XorA<<" m_XorB=0x"<<m_XorB<<endl;
               m_XorNumErr++;
           } else {
               m_XorNumOK++;
           }
       }

       //drive data for next checking
       m_XorA = GenUnsigned(); m_XorB = GenUnsigned(); m_XorRes = m_XorA ^ m_XorB;
       SH::m_Sigxor_a = m_XorA; SH::m_Sigxor_b = m_XorB;
   }
   cout<<"DriveCheckAlwaysXorTP NoErr="<<m_XorNumErr<<" NoOK=" << m_XorNumOK << endl;
}

void        Driver::DriveCheckAlwaysXorFast()
{
   static unsigned cnt = 0;
   if (cnt++) {
       if (m_XorRes != SH::m_Sigxor_res) {
           cout<<cnt<<": Error ***: m_XorA=0x"<<hex<<m_XorA<<" m_XorB=0x"<<m_XorB<<endl;
           m_XorNumErr++;
       } else {
           m_XorNumOK++;
       }
   }

   //Set data and calculate expected for next negedge.
   m_XorA = GenUnsigned(); m_XorB = GenUnsigned(); m_XorRes = m_XorA ^ m_XorB;
   SH::m_Sigxor_a = m_XorA; SH::m_Sigxor_b = m_XorB;
   if (cnt > loopSize) {
       CurrAProc()->Kill();
       cout<<"DriveCheckAlwaysXorFast NoErr="<< m_XorNumErr<< " NoOK="<<m_XorNumOK<<endl;
   }
}

///////////////////////////////////////////////////   SHIFTL //////////////////////////

void        Driver::DriveCheckAlwaysShiftLTP()
{
   for (unsigned i = 0; i < loopSize; i++) {
       if (i) {
           Wait(m_ClkShiftLNeg);
           if (m_ShiftLRes != SH::m_SigshiftL_res) {               
               cout<<i<<": Error ***: m_ShiftLA=0x"<<hex<<m_ShiftLA<<" m_ShiftLB=0x"<<endl;
               m_ShiftLNumErr++;
           } else {
               m_ShiftLNumOK++;
           }
       }
       m_ShiftLA=GenUnsigned();m_ShiftLB=GenUnsigned(0,31);

       m_ShiftLRes=m_ShiftLA<< m_ShiftLB;
       SH::m_SigshiftL_a = m_ShiftLA; SH::m_SigshiftL_b = m_ShiftLB;
   }
   cout<<"Drive..AlwaysShiftLTP NoErr=" <<m_ShiftLNumErr<<" NoOK="<<m_ShiftLNumOK<< endl;
}

void        Driver::DriveCheckAlwaysShiftLFast()
{
   static unsigned cnt = 0;
   if (cnt++) {
       if (m_ShiftLRes != SH::m_SigshiftL_res) {
           cout << cnt << ": Error ***: m_ShiftLA = 0x" << hex << m_ShiftLA << " m_ShiftLB = 0x" << m_ShiftLB << " SPV result = 0x" << m_ShiftLRes << " HDL m_SigshiftL_res = " << SH::m_SigshiftL_res(SpvHex) << dec << " T:" << SimTime() << endl;
           m_ShiftLNumErr++;
       }
       else {
           m_ShiftLNumOK++;
       }
   }
   //Set data ShiftL calculate expected for next negedge.
   m_ShiftLA = GenUnsigned(); m_ShiftLB = GenUnsigned(0, 31); m_ShiftLRes = m_ShiftLA << m_ShiftLB;
   SH::m_SigshiftL_a = m_ShiftLA; SH::m_SigshiftL_b = m_ShiftLB;
   if (cnt > loopSize) {
       CurrAProc()->Kill();
       cout << "DriveCheckAlwaysShiftLFast m_ShiftLNumErr=" << m_ShiftLNumErr << " m_ShiftLNumOK = " << m_ShiftLNumOK << endl;
   }
}

///////////////////////////////////////////////////   SHIFTR ////////////////////////////////////////////////////////////

void        Driver::DriveCheckAlwaysShiftRTP()
{
   for (unsigned i = 0; i < loopSize; i++) {
       if (i) {
           Wait(m_ClkShiftRNeg);
           if (m_ShiftRRes != SH::m_SigshiftR_res) {
               //cout << i << ": Error ***: m_ShiftRA = " << m_ShiftRA(SpvHex) << " m_ShiftRB = " << m_ShiftRB(SpvHex) << " SPV result = " << m_ShiftRRes(SpvHex) << " HDL m_SigregShiftRC = " << SH::m_SigregShiftRC(SpvHex) << " T:" << SimTime() << endl;
               cout << i << ": Error ***: m_ShiftRA = 0x" << hex << m_ShiftRA << " m_ShiftRB = 0x" << m_ShiftRB << " SPV result = 0x" << m_ShiftRRes << " HDL m_SigshiftR_res = " << SH::m_SigshiftR_res(SpvHex) << dec << " T:" << SimTime() << endl;
               m_ShiftRNumErr++;
           }
           else {
               m_ShiftRNumOK++;
           }
       }
       m_ShiftRA = GenUnsigned(0, 0x7FFFFFFF); m_ShiftRB = GenUnsigned(0, 31); m_ShiftRRes = m_ShiftRA >> m_ShiftRB;
       SH::m_SigshiftR_a = m_ShiftRA; SH::m_SigshiftR_b = m_ShiftRB;
   }
   cout << "DriveCheckAlwaysShiftRTP m_ShiftRNumErr=" << m_ShiftRNumErr << " m_ShiftRNumOK = " << m_ShiftRNumOK << endl;
   cout << " Num of iteration " << loopSize << " in all method T:" << SimTime() << endl;
   StopSim();//this is the most long process.
}

void        Driver::DriveCheckAlwaysShiftRFast()
{
   static unsigned cnt = 0;
   if (cnt++) {
       if (m_ShiftRRes != SH::m_SigshiftR_res) {
           cout << cnt << ": Error ***: m_ShiftRA = 0x" << hex << m_ShiftRA << " m_ShiftRB = 0x" << m_ShiftRB << " SPV result = 0x" << m_ShiftRRes << " HDL m_SigshiftR_res = " << SH::m_SigshiftR_res(SpvHex) << dec << " T:" << SimTime() << endl;
           m_ShiftRNumErr++;
       }
       else {
           m_ShiftRNumOK++;
       }
   }
   //Set data ShiftR calculate expected for next negedge.
   m_ShiftRA = GenUnsigned(0, 0x7FFFFFFF); m_ShiftRB = GenUnsigned(0, 31); m_ShiftRRes = m_ShiftRA >> m_ShiftRB;
   SH::m_SigshiftR_a = m_ShiftRA; SH::m_SigshiftR_b = m_ShiftRB;
   if (cnt > loopSize) {
       //StopSim();//this is the most long process.
       CurrAProc()->Kill();
       cout << "DriveCheckAlwaysShiftRFast m_ShiftRNumErr=" << m_ShiftRNumErr << " m_ShiftRNumOK = " << m_ShiftRNumOK << endl;
   }
}

//////////////////////////////////    CURLED //////////////////////

void      Driver::DriveCruledAlwaysTP()
{

}


void    Driver::DriveCruledAlwaysFast()
{
   static unsigned cnt = 0;    
   if (cnt++) {
       bool isErr = false;
       if (m_CurledA(0, 9).Uint() != SH::m_SigwireC.Uint()) {
           cout<<cnt<<": Error***: m_CurledA(0,9)=0x"<<hex<<m_CurledA(0,9).Uint();

           cout<<" !=wireC=0x"<<wireC.Uint()<<dec<<" T:"<<SimTime()<< endl;
           isErr = true;
       }
       SPV_UINT64 last34 = m_CurledA.Uint64() >> 30, sig34 = SH::m_SigwireA.Uint64();
       if (last34  != sig34) {
           cout<<cnt<<":Error***: m_CurledA(63,63-34+1)=0x"<<m_CurledA(63,63-34+ 1).Uint() ;          cout<<"!=wireA=0x"<<SH::m_SigwireA.Uint()<<dec<<" T:"<<SimTime()<<endl;
           isErr = true;
       }        
     
 //Need to check also SH::m_SigwireB.Uint() -- it is mix with Z|X
       m_CruledNumErr    = (isErr) ? (m_CruledNumErr + 1)    :    m_CruledNumErr ;
       m_CruledNumOK   = (isErr) ? m_CruledNumOK            :    (m_CruledNumOK + 1);
   }    
   
//Set value, so hdl will make curled process
   SH::m_SigregA = m_RegAVec.Gen();
   SH::m_SigregB = m_RegBVec.Gen();
   SH::m_SigregC = m_RegCVec.Gen();
   SH::m_SigregD = m_RegDVec.Gen();   

   m_CurledA[0]    = m_RegDVec[3];
   m_CurledA(1, 3) = m_RegDVec(0,2).Uint();
   m_CurledA(4, 10)= m_RegCVec;
   m_CurledA(11,14)= m_RegBVec;
   
//Literal & m_ConstCurled are const so they are there.
   m_CurledA(64-9,63)= m_RegAVec;
   //m_CurledB is const always

    if (cnt > loopSize) {                
       cout<<"DriveCruledFast NoErr="<<m_CruledNumErr<<" NoOK = "<<m_CruledNumOK<< endl;
       CurrAProc()->Kill();
       StopSim();//this is the most long process.
   }
}

     

SPV Basic environment content::

 

 

The basic SPV library enable build your simple verification environment and it includes the following general classes.

  • Generation classes.

    • Create values-dependent constraints.

    • Creation of structures, dependent on constraints and connections between different fields (package).

  • Coverage classes:​

    • Coverage declaration:​

      • Cross and single coverage.​

      • Coverage items declaration.

      • Coverage deriving verification, enable achieve 100% coverage and 100% efficiency.

  • Bits Manipulation:​

    • class SpvBitVec​ :

      • behave like integer {unlimited size).

      • All mathematical operation. ​

      • A data structure similar to the 'PLI' interface {Used for quick information transfer between the environment and the simulator }

      • Used for generating random numbers and values, creating packages for communication protocols, and any manipulation of bits.

  • MATLAb Runtime integration.

    • enable call any 'm' file with 'ENG' open mode (MATLAB with GUI).​

    • Enable call  any MATLAB  function by using MCC compiler.

    • SPV supply classes to deal  with any MATLAB data structure like:

      • Struct.​

      • Elements (List)

      • DoubleArray (Complex and not complex).

      • Cell.

      • strings.

      • MatFile.

      • Struct walker.

      • other

    • SPV loads one DLL per project, all the objects created are in the same running process.​

    • Using DPF to deal with MATLAB make it.

      • Faster (Performance 10X  VS files).​

      • Easy of use.

      • enable connect any information from MATLAB to HDL, from HDL to MATLAB.

    • More ...

  • SPV Scheduler and simulator interface.​

    • Read/Write access to any element in VHDL/Verilog​. 

    • Event driven:

      • SPV enable wait to any HDL event like:​

        • Posedge, Negedge, Change, =<>!= value of any signal in design.​

      • Wait time.​

    • Read/Write slice,  'X', 'Z' , bin and mix.​

    • Deal with any signal size.

    • TCM that behave like thread,  with Wait  events in loop or not.

    • Example:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

bottom of page