// DESCRIPTION: SystemPerl: Example source module
//
// Copyright 2001-2013 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the
// GNU Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
#sp interface // Comment
#include <systemperl.h>
#include <iostream>
#include "SpCoverage.h"
/*AUTOSUBCELL_CLASS*/
class ExModSubEnum {
public:
enum en {
ONE=1,
TWO,
THREE=3, NINE=9, TWENTYSEVEN=27
};
/*AUTOENUM_CLASS(ExModSubEnum.en)*/
};
/*AUTOENUM_GLOBAL(ExModSubEnum.en)*/
#include <iostream>
#include <stdint.h>
// Vregs-style enum class:
class ExModSubVregsEnum {
public:
enum en {
INV = 0x0,
EXCLUSIVE = 0x4,
MODIFIED = 0x5,
SHARED = 0x6,
OWNED = 0x7,
MAX = 0x8 ///< MAXIMUM+1
};
enum en m_e;
inline ExModSubVregsEnum () {}
inline ExModSubVregsEnum (en _e) : m_e(_e) {}
explicit inline ExModSubVregsEnum (int _e) : m_e(static_cast<en>(_e)) {}
operator const char* () const { return ascii(); }
operator en () const { return m_e; }
const char* ascii() const;
inline bool valid() const { return *ascii()!='?'; };
class iterator {
en m_e; public:
inline iterator(en item) : m_e(item) {};
iterator operator++();
inline operator ExModSubVregsEnum () const { return ExModSubVregsEnum(m_e); }
inline ExModSubVregsEnum operator*() const { return ExModSubVregsEnum(m_e); }
};
static iterator begin() { return iterator(INV); }
static iterator end() { return iterator(MAX); }
};
inline bool operator== (ExModSubVregsEnum lhs, ExModSubVregsEnum rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (ExModSubVregsEnum lhs, ExModSubVregsEnum::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (ExModSubVregsEnum::en lhs, ExModSubVregsEnum rhs) { return (lhs == rhs.m_e); }
inline bool operator!= (ExModSubVregsEnum lhs, ExModSubVregsEnum rhs) { return (lhs.m_e != rhs.m_e); }
inline bool operator!= (ExModSubVregsEnum lhs, ExModSubVregsEnum::en rhs) { return (lhs.m_e != rhs); }
inline bool operator!= (ExModSubVregsEnum::en lhs, ExModSubVregsEnum rhs) { return (lhs != rhs.m_e); }
inline bool operator< (ExModSubVregsEnum lhs, ExModSubVregsEnum rhs) { return lhs.m_e < rhs.m_e; }
inline ostream& operator<< (ostream& lhs, const ExModSubVregsEnum& rhs) { return lhs << rhs.ascii(); }
class MySigStruct {
public:
SP_TRACED bool m_in;
SP_TRACED bool m_out;
sc_bv<72> m_outbx;
MySigStruct() {}
MySigStruct(bool i, bool o, bool ob) : m_in(i), m_out(o), m_outbx(ob) {}
};
inline bool operator== (const MySigStruct &lhs, const MySigStruct &rhs) {
return 0==memcmp(&lhs, &rhs, sizeof(lhs)); };
inline ostream& operator<< (ostream& lhs, const MySigStruct& rhs) {
return lhs;}
SC_MODULE (__MODULE__) {
sc_in_clk clk; // **** System Inputs
sc_in<bool> in;
sc_out<sp_ui<0,0> > out;
sc_out<bool> outbx;
sc_signal<MySigStruct> m_sigstr1;
SP_TRACED MySigStruct m_sigstr2;
sc_signal<sp_ui<96,5> > m_sigstr3; // becomes sc_bv
SP_TRACED sp_ui<31,-1> m_sigstr4; // becomes uint64_t
SP_TRACED sp_ui<10,1> m_sigstr5; // becomes uint32_t
sp_ui<96,5> m_member3;
sp_ui<31,-1> m_member4;
sp_ui<10,1> m_member5;
sc_signal<sp_ui<31,0> > m_var32;
sc_signal<sp_ui<63,0> > m_var64;
ExModSubEnum m_autoEnumVar;
ExModSubVregsEnum m_vregsEnumVar;
SP_COVERGROUP example_group (
page = "my example coverage group";
option per_instance = 1; // this group is covered separately per instance
coverpoint in;
);
SP_COVERGROUP example_group2 (
description = "2nd example group, \"with backslashed quotes\"";
coverpoint in;
coverpoint in(in_alternate_name);
coverpoint out;
coverpoint out(out_alt_name)[16] = [0:0x7ff] { // hex is supported
description = "comments for a range";
option radix = 16; // name the bins in hex
};
coverpoint out(out_alt_name2)[16] = [0:0xf] {
// if size is exact, bin names are truncated to just the number
option radix = 2; // name the bins in binary
};
coverpoint m_var64[0x10];
// These require a 64-bit perl
//coverpoint m_var64(bigaddr)[16] = [0:0xffffffffffff]; // more than 32 bits
//coverpoint m_var64(verybigaddr)[16] = [0:0xffffffffffffffff]; // all fs
coverpoint m_var64(bigaddr)[16] = [0:0xfffffff];
coverpoint m_var64(verybigaddr)[16] = [0:0xffffffff];
coverpoint m_var32 {
bins zero = 0;
bins few = [ExModSubEnum::ONE:ExModSubEnum::TWO]; // can use enums on the RHS in ranges
bins few = [3:5];
bins scatter[] = {6,9,[11:15]}; // list multiple bins
illegal_bins ill = 16; // illegal bins
illegal_bins ill2[] = {17,[19:24]};
bins several[] = [90:105]; // a bin per value in a range
bins dist_ranges[4] = [200:299]; // 4 bins spread over a range
ignore_bins ign = 0xffc0; // ignore bins
ignore_bins_func = var32_ignore_func(); // ignore bins by function
illegal_bins_func = var32_illegal_func(); // illegal bins by function
limit_func = var32_limit_func(); // change CovVise limit by function
bins other = default; // named default
};
);
SP_COVERGROUP vregs_enum_example (
description = "vregs-style enum";
coverpoint m_vregsEnumVar {
auto_enum_bins = ExModSubVregsEnum; // make a bin for each enum value
};
);
SP_COVERGROUP timing_window_example (
description = "example of a timing window";
// 9 bins +/- event1 occuring 4 samples before/after event2
window myWin(in,out,4);
window myWin2(in,out,6) {
description = "windows can have descriptions";
page = "window page";
option radix = 16; // name the bins in hex
ignore_bins_func = window_ignore_func();
limit_func = window_limit_func();
};
);
SP_COVERGROUP autoenum_example (
description = "enumerated type coverage";
// both of these coverpoints are the same; the latter is automatic
coverpoint m_autoEnumVar {
description = "points can have descriptions too";
bins ONE = 1;
bins TWO = 2;
bins THREE = ExModSubEnum::THREE; // can use enums on the RHS
bins NINE = 9;
bins TWENTYSEVEN = 27;
};
coverpoint m_autoEnumVar(automatic_autoEnumVar) {
auto_enum_bins = ExModSubEnum; // make a bin for each enum value
page = "automatic enum page";
};
);
SP_COVERGROUP cross_example (
description = "cross coverage";
coverpoint m_vregsEnumVar {
auto_enum_bins = ExModSubVregsEnum; // make a bin for each enum value
};
coverpoint m_autoEnumVar {
auto_enum_bins = ExModSubEnum; // make a bin for each enum value
description = "this text goes above the point table";
page = "put this table on a separate page";
};
cross myCross {
description = "this text goes above the cross table";
page = "put this table on another separate page";
rows = {m_autoEnumVar};
cols = {m_vregsEnumVar};
ignore_bins_func = cross_ignore_func(); // ignore bins by function
illegal_bins_func = cross_illegal_func(); // illegal bins by function
limit_func = cross_limit_func(); // change CovVise limit by function
option max_bins = 0x2000; // allow more than the usual 1024 bins
};
);
private:
/*AUTOSUBCELL_DECL*/
/*AUTOSIGNAL*/
public:
/*AUTOMETHODS*/
bool var32_ignore_func(uint64_t var32) { return (var32 % 5 == 3); } // ignore all values 3 mod 5
bool var32_illegal_func(uint64_t var32) { return (var32 == 1000); } // illegal 1000
uint32_t var32_limit_func(uint64_t var32) { return (var32); } // return = value
bool window_ignore_func(uint64_t cycles) { return (cycles < 3); } // ignore all counts < 3
uint32_t window_limit_func(uint64_t cycles) { return (cycles / 2); }
bool cross_ignore_func(uint64_t autoenum, uint64_t vregsenum) { return (autoenum == vregsenum); }
bool cross_illegal_func(uint64_t autoenum, uint64_t vregsenum) { return (autoenum == ExModSubEnum::NINE) && (vregsenum == ExModSubVregsEnum::MODIFIED); }
uint32_t cross_limit_func(uint64_t autoenum, uint64_t vregsenum) { return (autoenum == ExModSubEnum::NINE) ? 9 : 123; }
};
//######################################################################
#sp slow // Comment
/*AUTOSUBCELL_INCLUDE*/
SP_CTOR_IMP(__MODULE__) /*AUTOINIT*/ {
SP_AUTO_CTOR;
SP_AUTO_COVER(); // only once
m_var64 = 0;
m_var32 = 0;
m_autoEnumVar = ExModSubEnum::ONE;
#sp ifdef NEVER // Comment
// We ignore this
SP_CELL(ignored,IGNORED_CELL);
SP_PIN (ignored,ignore_pin,ignore_pin);
/*AUTO_IGNORED_IF_OFF*/
# sp ifdef NEVER_ALSO /*Comment*/
SP_CELL(ignored2,IGNORED2_CELL);
# sp else // Comment
SP_CELL(ignored3,IGNORED2_CELL);
# sp endif // Comment
#sp else
# sp ifdef NEVER_ALSO
SP_CELL(ignored3,IGNORED3_CELL);
# sp else
SP_AUTO_COVER();
# sp endif
#sp endif
#sp ifndef NEVER
SP_AUTO_COVER();
#sp else
SP_CELL(ifdefoff,IGNORED_CELL);
#sp endif
// Other coverage scheme
SP_AUTO_COVER_CMT("Commentary");
if (0) { SP_AUTO_COVER_CMT("Never_Occurs"); }
if (0) { SP_AUTO_COVER_CMT_IF("Not_Possible",0); }
SP_AUTO_COVER_CMT_IF("Always_Occurs",(1||1)); // If was just '1' SP would short-circuit the eval
for (int i=0; i<3; i++) {
static uint32_t coverValue = 100;
SP_COVER_INSERT(&coverValue, "comment","Hello World",
"instance",SpCvtToCStr(i),
"per_instance","1" );
}
}
//######################################################################
#sp implementation // Comment
/*AUTOSUBCELL_INCLUDE*/
//ExModSubVregsEnum
const char* ExModSubVregsEnum::ascii () const {
switch (m_e) {
case INV: return("INV");
case EXCLUSIVE: return("EXCLUSIVE");
case MODIFIED: return("MODIFIED");
case SHARED: return("SHARED");
case OWNED: return("OWNED");
default: return ("?E");
}
}
ExModSubVregsEnum::iterator ExModSubVregsEnum::iterator::operator++() {
switch (m_e) {
case EXCLUSIVE: /*FALLTHRU*/
case MODIFIED: /*FALLTHRU*/
case SHARED: m_e=ExModSubVregsEnum(m_e + 1); return *this;
case INV: m_e=EXCLUSIVE; return *this;
default: m_e=MAX; return *this;
}
}
void __MODULE__::clock() {
// Below will declare the SC_METHOD and sensitivity to the clock
SP_AUTO_METHOD(clock, clk.pos());
SP_AUTO_COVER1("clocking"); // not in line report
out.write(in.read());
outbx.write(in.read());
m_sigstr1.write(MySigStruct(in,out,outbx));
m_sigstr2 = MySigStruct(in,out,outbx);
m_var64 = m_var64 + (1 << 28);
m_var32 = m_var32 + (10);
if (m_autoEnumVar != ExModSubEnum::NINE)
m_autoEnumVar = ExModSubEnum((int)m_autoEnumVar + 1);
if (m_autoEnumVar == ExModSubEnum::TWO)
m_vregsEnumVar = ExModSubVregsEnum::MODIFIED;
else
m_vregsEnumVar = ExModSubVregsEnum::SHARED;
SP_AUTO_COVER();
SP_COVER_SAMPLE(cross_example);
SP_COVER_SAMPLE(vregs_enum_example);
SP_COVER_SAMPLE(timing_window_example);
SP_COVER_SAMPLE(autoenum_example);
SP_COVER_SAMPLE(example_group);
if (in.read()) {
SP_COVER_SAMPLE(example_group2);
}
}
/*AUTOTRACE(__MODULE__)*/