SystemC 学习之 SystemC 验证库(七)

1、下载 SystemC 验证库

wget lhttps://www.accellera.org/images/downloads/standards/systemc/scv-2.0.1.tar.gz

解压缩

tar -xf scv-2.0.1.tar.gz 

2、编译 SystemC 验证库

cd scv-2.0.1
mkdir build
cd build
../configure --with-systemc=/opt/systemc CXXFLAGS="-std=c++11" CFLAGS="-std=c11"
make -j CXXFLAGS=-DSC_DISABLE_API_VERSION_CHECK
sudo make install

/opt/systemc/ 这里是之前编译 systemc 产物的路径

编译成功之后,scv 的产物会放在和 systemc 产物相同的路径

编译运行测试例子

cd ../examples/data_structures/scv_bag
g++ test.cc -std=c++11 -lscv -lsystemc
./a.out

能编译运行成功,说明整个 scv 验证库的编译和运行没有问题了

3、SystemC 验证库功能

Systemc 验证库 SCV2.0 为构建高级的 systemc 可重用的验证 IP 提供语言功能,主要包括

  1. 数据内查

  2. 随机数产生,随即种子管理

  3. 约束的随机化

  4. 变量和事务的记录

除了上述各项,SCV 还包括了一些对编写验证平台非常有用的语言功能,主要包括

  1. 到其他硬件描述语言的接口

  2. 常见数据结构的小集合

  3. 异常处理

  4. 调试

4、基本语法

复杂用户数据类型扩展

struct Color {
    sc_uint<8> red;
    sc_uint<8> green;
    sc_uint<8> blue;
    sc_uint<8> alpha;

    Color& operator=(const Color& rhs) {
        red   = rhs.red;
        green = rhs.green;
        blue  = rhs.blue;
        alpha = rhs.alpha;
        return *this;
    }
    
    friend ostream& operator<< (ostream& os, const Color& p) {
        os << "   red: " << std::setw(3) << p.red
           << " green: " << std::setw(3) << p.green
           << "  blue: " << std::setw(3) << p.blue
           << " alpha: " << std::setw(3) << p.alpha;
        return os;
    }
};

template<>
class scv_extensions : public scv_extensions_base {
public:
  scv_extensions> red;
  scv_extensions> green;
  scv_extensions> blue;
  scv_extensions> alpha;

  SCV_EXTENSIONS_CTOR(Color) {
    //must be in order
    SCV_FIELD(red);
    SCV_FIELD(green);
    SCV_FIELD(blue);
    SCV_FIELD(alpha);
  }
};

枚举类型扩展

enum PrimitiveType {
    kPrimitiveTypePoint;
    kPrimitiveTypeLine;
    kPrimitiveTypeTriangle;
};

struct PrimitiveInfo {
    PrimitiveType type;
    uint32_t attribute_count;
};

template<>
class scv_extensions : public scv_enum_base< {
public:
    SCV_ENUM_CTOR(PrimitiveType) {
        SCV_ENUM(kPrimitiveTypePoint);
        SCV_ENUM(kPrimitiveTypeLine);
        SCV_ENUM(kPrimitiveTypeTriangle);
    }
};
template<>
class scv_extensions : public scv_extensions_base {
public:
  scv_extensions type;
  scv_extensions attribute_count;

  SCV_EXTENSIONS_CTOR(PrimitiveInfo) {
    //must be in order
    SCV_FIELD(type);
    SCV_FIELD(attribute_count);
  }
};

设置取值范围

// 固定某一个值
void keep_only(const T& value);
// 设置一个范围
void keep_only(const T& lb, const T& ub);
// 设置某几个值
void keep_only(const std::list& vlist);
// 设置不取某个值
void keep_out(const T& value);
// 设置不取范围内的值
void keep_out(const T& lb, const T& ub);
// 设置不取某几个值
void keep_out(const std::list& vlist);

设置权重

scv_bag > dist;
dist.add(10, 50);   // 取值为 10 的概率为 50%
dist.add(15, 30);   // 取值为 15 的概率为 15%
dist.add(20, 20);   // 取值为 20 的概率为 20%
p->alpha.set_mode(dist);

设置约束

约束类:scv_constraint_base,约束类用于定义约束,以及将多个复杂和简单约束合并在一起成为一个更复杂的约束

struct addr_constraint : public scv_constraint_base {
    // 定义需要约束的变量
    scv_smart_ptr row;
    scv_smart_ptr col;
    // 构造函数
    SCV_CONSTRAINT_CTOR(addr_constraint) {
        std::string name = std::string(get_name()) + ".row";
        row->set_name(name.c_str());
        name = std::string(get_name()) + ".col";
        col->set_name(name.c_str());
    }
    // 设置约束条件
    SCV_SOFT_CONSTRAINT((row() > 10 && row() < 50) ||
                        (row() >= 200 && row() <= 250));
    SCV_CONSTRAINT ( col() > ( row() - 5) );
    SCV_CONSTRAINT ( col() < ( row() + 20) );
    
};
int sc_main(int argc, char* argv[]) {
    scv_random::set_global_seed(0xCCCC);
    addr_constraint addr("addr");
    addr.col->disable_randomization();
    *(addr.col) = 1000;
    addr.next();
    scv_out << addr.row->get_name() << " = " << *(addr.row) << "\n"
            << addr.col->get_name() << " = " << *(addr.col) << "\n" << endl;
    return 0;
}

软约束和硬约束的区别

软约束失败,会给出一个警告,但是不会影响运行,只不过产生的值会是一个随机值,不再受约束

硬约束失败,除了会给出一个警告以外,还会产生错误,程序会直接报错

scv_smart_ptr

scv_smart_ptr 类型的对象可以通过调用 next() 函数产生均匀分布的随机数

scv_bag

scv_bag 可以为随机数设置加权的分布,使得 scv_smart_ptr 类型的对象的 next() 函数返回的随机数的分布满足所设置的加权分布

scv_bag 的成员函数

void add(const T& arg, int num=1);  // 将产生的随机对象加入到袋子中
void push(const T& arg, int num = 1);  // 和 add 一样
// 在袋子中取一个随机对象,并设置是否将当前对象标记为 mark 状态
// peekRandom 只能取出 unmark 状态的值
const T& peekRandom(bool mark = false);
// 表示是否将上一次取出的对象标记为 mark 状态
void mark(bool AllCopies = false);
// 将袋子中的所有对象都标记为 mark 状态
void markAll();
void mark_all();
// 取消袋子中的所有对象的 mark 状态
void unmarkAll();
void unmark_all();

随机取值

// 随机在给定条件下取值
void next();

你可能感兴趣的:(systemc,systemc)