Support .
This commit is contained in:
parent
c4b9f4bccf
commit
7bf3366041
2
Changes
2
Changes
|
|
@ -6,6 +6,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||||
|
|
||||||
*** Add +verilator+seed, bug1396. [Stan Sokorac]
|
*** Add +verilator+seed, bug1396. [Stan Sokorac]
|
||||||
|
|
||||||
|
*** Support $fread. [Leendert van Doorn]
|
||||||
|
|
||||||
**** Report PORTSHORT errors on concat constants, bug 1400. [Will Korteland]
|
**** Report PORTSHORT errors on concat constants, bug 1400. [Will Korteland]
|
||||||
|
|
||||||
**** Fix VERILATOR_GDB being ignored, msg2860. [Yu Sheng Lin]
|
**** Fix VERILATOR_GDB being ignored, msg2860. [Yu Sheng Lin]
|
||||||
|
|
|
||||||
|
|
@ -1384,6 +1384,59 @@ void VL_WRITEMEM_N(
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IData VL_FREAD_I(int width, int array_lsb, int array_size,
|
||||||
|
void* memp, IData fpi, IData start, IData count) VL_MT_SAFE {
|
||||||
|
// While threadsafe, each thread can only access different file handles
|
||||||
|
FILE* fp = VL_CVT_I_FP(fpi);
|
||||||
|
if (VL_UNLIKELY(!fp)) return 0;
|
||||||
|
if (count > (array_size - (start - array_lsb))) count = array_size - (start - array_lsb);
|
||||||
|
// Prep for reading
|
||||||
|
IData read_count = 0;
|
||||||
|
IData read_elements = 0;
|
||||||
|
int start_shift = (width-1) & ~7; // bit+7:bit gets first character
|
||||||
|
int shift = start_shift;
|
||||||
|
// Read the data
|
||||||
|
// We process a character at a time, as then we don't need to deal
|
||||||
|
// with changing buffer sizes dynamically, etc.
|
||||||
|
while (1) {
|
||||||
|
int c = fgetc(fp);
|
||||||
|
if (VL_UNLIKELY(c==EOF)) break;
|
||||||
|
// Shift value in
|
||||||
|
IData entry = read_elements + start - array_lsb;
|
||||||
|
if (width <= 8) {
|
||||||
|
CData* datap = &(reinterpret_cast<CData*>(memp))[entry];
|
||||||
|
if (shift == start_shift) { *datap = 0; }
|
||||||
|
*datap |= (c << shift) & VL_MASK_I(width);
|
||||||
|
} else if (width <= 16) {
|
||||||
|
SData* datap = &(reinterpret_cast<SData*>(memp))[entry];
|
||||||
|
if (shift == start_shift) { *datap = 0; }
|
||||||
|
*datap |= (c << shift) & VL_MASK_I(width);
|
||||||
|
} else if (width <= VL_WORDSIZE) {
|
||||||
|
IData* datap = &(reinterpret_cast<IData*>(memp))[entry];
|
||||||
|
if (shift == start_shift) { *datap = 0; }
|
||||||
|
*datap |= (c << shift) & VL_MASK_I(width);
|
||||||
|
} else if (width <= VL_QUADSIZE) {
|
||||||
|
QData* datap = &(reinterpret_cast<QData*>(memp))[entry];
|
||||||
|
if (shift == start_shift) { *datap = 0; }
|
||||||
|
*datap |= ((static_cast<QData>(c) << static_cast<QData>(shift))
|
||||||
|
& VL_MASK_Q(width));
|
||||||
|
} else {
|
||||||
|
WDataOutP datap = &(reinterpret_cast<WDataOutP>(memp))[ entry*VL_WORDS_I(width) ];
|
||||||
|
if (shift == start_shift) { VL_ZERO_RESET_W(width, datap); }
|
||||||
|
datap[VL_BITWORD_I(shift)] |= (c << VL_BITBIT_I(shift));
|
||||||
|
}
|
||||||
|
// Prep for next
|
||||||
|
++read_count;
|
||||||
|
shift -= 8;
|
||||||
|
if (shift < 0) {
|
||||||
|
shift = start_shift;
|
||||||
|
++read_elements;
|
||||||
|
if (VL_UNLIKELY(read_elements >= count)) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return read_count;
|
||||||
|
}
|
||||||
|
|
||||||
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
|
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
|
||||||
QData filename, void* memp, IData start, IData end) VL_MT_SAFE {
|
QData filename, void* memp, IData start, IData end) VL_MT_SAFE {
|
||||||
WData fnw[2]; VL_SET_WQ(fnw, filename);
|
WData fnw[2]; VL_SET_WQ(fnw, filename);
|
||||||
|
|
|
||||||
|
|
@ -594,6 +594,9 @@ inline IData VL_FOPEN_II(IData filename, IData mode) VL_MT_SAFE {
|
||||||
|
|
||||||
extern void VL_FCLOSE_I(IData fdi);
|
extern void VL_FCLOSE_I(IData fdi);
|
||||||
|
|
||||||
|
extern IData VL_FREAD_I(int width, int array_lsb, int array_size,
|
||||||
|
void* memp, IData fpi, IData start, IData count);
|
||||||
|
|
||||||
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||||
WDataInP filenamep, void* memp, IData start, IData end);
|
WDataInP filenamep, void* memp, IData start, IData end);
|
||||||
extern void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords,
|
extern void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||||
|
|
|
||||||
|
|
@ -2741,6 +2741,42 @@ public:
|
||||||
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
|
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AstFRead : public AstNodeMath {
|
||||||
|
// Parents: expr
|
||||||
|
// Children: varrefs to load
|
||||||
|
// Children: file which must be a varref
|
||||||
|
// Children: low index
|
||||||
|
// Children: count
|
||||||
|
public:
|
||||||
|
AstFRead(FileLine* fileline, AstNode* memp, AstNode* filep,
|
||||||
|
AstNode* startp, AstNode* countp)
|
||||||
|
: AstNodeMath(fileline) {
|
||||||
|
setOp1p(memp);
|
||||||
|
setOp2p(filep);
|
||||||
|
setNOp3p(startp);
|
||||||
|
setNOp4p(countp);
|
||||||
|
}
|
||||||
|
ASTNODE_NODE_FUNCS(FRead)
|
||||||
|
virtual string verilogKwd() const { return "$fread"; }
|
||||||
|
virtual string emitVerilog() { V3ERROR_NA; return ""; }
|
||||||
|
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||||
|
virtual bool isGateOptimizable() const { return false; }
|
||||||
|
virtual bool isPredictOptimizable() const { return false; }
|
||||||
|
virtual bool isPure() const { return false; } // SPECIAL: has 'visual' ordering
|
||||||
|
virtual bool isOutputter() const { return true; } // SPECIAL: makes output
|
||||||
|
virtual bool cleanOut() { return false; }
|
||||||
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||||
|
virtual bool same(const AstNode* samep) const { return true; }
|
||||||
|
AstNode* memp() const { return op1p(); }
|
||||||
|
void memp(AstNode* nodep) { setOp1p(nodep); }
|
||||||
|
AstNode* filep() const { return op2p(); }
|
||||||
|
void filep(AstNode* nodep) { setOp2p(nodep); }
|
||||||
|
AstNode* startp() const { return op3p(); }
|
||||||
|
void startp(AstNode* nodep) { setNOp3p(nodep); }
|
||||||
|
AstNode* countp() const { return op4p(); }
|
||||||
|
void countp(AstNode* nodep) { setNOp4p(nodep); }
|
||||||
|
};
|
||||||
|
|
||||||
class AstFScanF : public AstNodeMath {
|
class AstFScanF : public AstNodeMath {
|
||||||
// Parents: expr
|
// Parents: expr
|
||||||
// Children: file which must be a varref
|
// Children: file which must be a varref
|
||||||
|
|
|
||||||
|
|
@ -387,6 +387,45 @@ public:
|
||||||
puts(")); }\n");
|
puts(")); }\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstFRead* nodep) {
|
||||||
|
puts("VL_FREAD_I(");
|
||||||
|
puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width
|
||||||
|
putbs(",");
|
||||||
|
bool memory = false;
|
||||||
|
uint32_t array_lsb = 0;
|
||||||
|
uint32_t array_size = 0;
|
||||||
|
{
|
||||||
|
const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef);
|
||||||
|
if (!varrefp) { nodep->v3error(nodep->verilogKwd() << " loading non-variable"); }
|
||||||
|
else if (VN_CAST(varrefp->varp()->dtypeSkipRefp(), BasicDType)) { }
|
||||||
|
else if (const AstUnpackArrayDType* adtypep
|
||||||
|
= VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) {
|
||||||
|
memory = true;
|
||||||
|
array_lsb = adtypep->lsb();
|
||||||
|
array_size = adtypep->elementsConst();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nodep->v3error(nodep->verilogKwd()
|
||||||
|
<< " loading other than unpacked-array variable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
puts(cvtToStr(array_lsb));
|
||||||
|
putbs(",");
|
||||||
|
puts(cvtToStr(array_size));
|
||||||
|
putbs(", ");
|
||||||
|
if (!memory) puts("&(");
|
||||||
|
iterateAndNextNull(nodep->memp());
|
||||||
|
if (!memory) puts(")");
|
||||||
|
putbs(", ");
|
||||||
|
iterateAndNextNull(nodep->filep());
|
||||||
|
putbs(", ");
|
||||||
|
if (nodep->startp()) iterateAndNextNull(nodep->startp());
|
||||||
|
else puts(cvtToStr(array_lsb));
|
||||||
|
putbs(", ");
|
||||||
|
if (nodep->countp()) iterateAndNextNull(nodep->countp());
|
||||||
|
else puts(cvtToStr(array_size));
|
||||||
|
puts(");\n");
|
||||||
|
}
|
||||||
virtual void visit(AstSysFuncAsTask* nodep) {
|
virtual void visit(AstSysFuncAsTask* nodep) {
|
||||||
if (!nodep->lhsp()->isWide()) puts("(void)");
|
if (!nodep->lhsp()->isWide()) puts("(void)");
|
||||||
iterateAndNextNull(nodep->lhsp());
|
iterateAndNextNull(nodep->lhsp());
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,15 @@ private:
|
||||||
}
|
}
|
||||||
m_setRefLvalue = last_setRefLvalue;
|
m_setRefLvalue = last_setRefLvalue;
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstFRead* nodep) {
|
||||||
|
bool last_setRefLvalue = m_setRefLvalue;
|
||||||
|
{
|
||||||
|
m_setRefLvalue = true;
|
||||||
|
iterateAndNextNull(nodep->memp());
|
||||||
|
iterateAndNextNull(nodep->filep());
|
||||||
|
}
|
||||||
|
m_setRefLvalue = last_setRefLvalue;
|
||||||
|
}
|
||||||
virtual void visit(AstFScanF* nodep) {
|
virtual void visit(AstFScanF* nodep) {
|
||||||
bool last_setRefLvalue = m_setRefLvalue;
|
bool last_setRefLvalue = m_setRefLvalue;
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -362,6 +362,10 @@ private:
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
|
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstFRead* nodep) {
|
||||||
|
iterateChildren(nodep);
|
||||||
|
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
|
||||||
|
}
|
||||||
virtual void visit(AstFScanF* nodep) {
|
virtual void visit(AstFScanF* nodep) {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
expectFormat(nodep, nodep->text(), nodep->exprsp(), true);
|
expectFormat(nodep, nodep->text(), nodep->exprsp(), true);
|
||||||
|
|
|
||||||
|
|
@ -2232,6 +2232,19 @@ private:
|
||||||
userIterateAndNext(nodep->strgp(), WidthVP(SELF,BOTH).p());
|
userIterateAndNext(nodep->strgp(), WidthVP(SELF,BOTH).p());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstFRead* nodep) {
|
||||||
|
if (m_vup->prelim()) {
|
||||||
|
nodep->dtypeSetSigned32(); // Spec says integer return
|
||||||
|
userIterateAndNext(nodep->memp(), WidthVP(SELF,BOTH).p());
|
||||||
|
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
|
||||||
|
if (nodep->startp()) {
|
||||||
|
iterateCheckSigned32(nodep, "$fread start", nodep->startp(), BOTH);
|
||||||
|
}
|
||||||
|
if (nodep->countp()) {
|
||||||
|
iterateCheckSigned32(nodep, "$fread count", nodep->countp(), BOTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
virtual void visit(AstFScanF* nodep) {
|
virtual void visit(AstFScanF* nodep) {
|
||||||
if (m_vup->prelim()) {
|
if (m_vup->prelim()) {
|
||||||
nodep->dtypeSetSigned32(); // Spec says integer return
|
nodep->dtypeSetSigned32(); // Spec says integer return
|
||||||
|
|
@ -3172,6 +3185,18 @@ private:
|
||||||
underp = iterateCheck(nodep,"file_descriptor",underp,SELF,FINAL,expDTypep,EXTEND_EXP);
|
underp = iterateCheck(nodep,"file_descriptor",underp,SELF,FINAL,expDTypep,EXTEND_EXP);
|
||||||
if (underp) {} // cppcheck
|
if (underp) {} // cppcheck
|
||||||
}
|
}
|
||||||
|
void iterateCheckSigned32(AstNode* nodep, const char* side, AstNode* underp, Stage stage) {
|
||||||
|
// Coerce child to signed32 if not already. Child is self-determined
|
||||||
|
// underp may change as a result of replacement
|
||||||
|
if (stage & PRELIM) {
|
||||||
|
underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, PRELIM).p());
|
||||||
|
}
|
||||||
|
if (stage & FINAL) {
|
||||||
|
AstNodeDType* expDTypep = nodep->findSigned32DType();
|
||||||
|
underp = iterateCheck(nodep, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP);
|
||||||
|
}
|
||||||
|
if (underp) {} // cppcheck
|
||||||
|
}
|
||||||
void iterateCheckReal(AstNode* nodep, const char* side, AstNode* underp, Stage stage) {
|
void iterateCheckReal(AstNode* nodep, const char* side, AstNode* underp, Stage stage) {
|
||||||
// Coerce child to real if not already. Child is self-determined
|
// Coerce child to real if not already. Child is self-determined
|
||||||
// e.g. nodep=ADDD, underp=ADD in ADDD(ADD(a,b), real-CONST)
|
// e.g. nodep=ADDD, underp=ADD in ADDD(ADD(a,b), real-CONST)
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||||
"$finish" { FL; return yD_FINISH; }
|
"$finish" { FL; return yD_FINISH; }
|
||||||
"$floor" { FL; return yD_FLOOR; }
|
"$floor" { FL; return yD_FLOOR; }
|
||||||
"$fopen" { FL; return yD_FOPEN; }
|
"$fopen" { FL; return yD_FOPEN; }
|
||||||
|
"$fread" { FL; return yD_FREAD; }
|
||||||
"$fscanf" { FL; return yD_FSCANF; }
|
"$fscanf" { FL; return yD_FSCANF; }
|
||||||
"$fullskew" { FL; return yaTIMINGSPEC; }
|
"$fullskew" { FL; return yaTIMINGSPEC; }
|
||||||
"$fwrite" { FL; return yD_FWRITE; }
|
"$fwrite" { FL; return yD_FWRITE; }
|
||||||
|
|
|
||||||
|
|
@ -475,6 +475,7 @@ class AstSenTree;
|
||||||
%token<fl> yD_FINISH "$finish"
|
%token<fl> yD_FINISH "$finish"
|
||||||
%token<fl> yD_FLOOR "$floor"
|
%token<fl> yD_FLOOR "$floor"
|
||||||
%token<fl> yD_FOPEN "$fopen"
|
%token<fl> yD_FOPEN "$fopen"
|
||||||
|
%token<fl> yD_FREAD "$fread"
|
||||||
%token<fl> yD_FSCANF "$fscanf"
|
%token<fl> yD_FSCANF "$fscanf"
|
||||||
%token<fl> yD_FWRITE "$fwrite"
|
%token<fl> yD_FWRITE "$fwrite"
|
||||||
%token<fl> yD_HIGH "$high"
|
%token<fl> yD_HIGH "$high"
|
||||||
|
|
@ -2815,6 +2816,9 @@ system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
|
||||||
| yD_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); }
|
| yD_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); }
|
||||||
| yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
|
| yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
|
||||||
| yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); }
|
| yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); }
|
||||||
|
| yD_FREAD '(' idClassSel ',' expr ')' { $$ = new AstFRead($1,$3,$5,NULL,NULL); }
|
||||||
|
| yD_FREAD '(' idClassSel ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,NULL); }
|
||||||
|
| yD_FREAD '(' idClassSel ',' expr ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,$9); }
|
||||||
| yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
|
| yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
|
||||||
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
||||||
| yD_HIGH '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,NULL); }
|
| yD_HIGH '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,NULL); }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
Dump:
|
||||||
|
r_i: 00010203
|
||||||
|
r_upb: 0e 0d 0c 0b 0a 09 08 07 06 05 04
|
||||||
|
r_dnb: 19 18 17 16 15 14 13 12 11 10 0f
|
||||||
|
r_ups: 2e2f 2c2d 2a2b 2829 2627 2425 2223 2021 1e1f 1c1d 1a1b
|
||||||
|
r_dns: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0041 0243 0445
|
||||||
|
r_upi: 6e6f7071 6a6b6c6d 66676869 62636465 5e5f6061 5a5b5c5d 56575859 52535455 4e4f5051 4a4b4c4d 46474849
|
||||||
|
r_dni: 72737475 76777879 7a7b7c7d 7e7f8081 02838485 06878889 0a8b8c8d 0e8f9091 12939495 16979899 1a9b9c9d
|
||||||
|
r_upq: 2eeff0f1f2f3f4f5 26e7e8e9eaebeced 1edfe0e1e2e3e4e5 16d7d8d9dadbdcdd 0ecfd0d1d2d3d4d5 06c7c8c9cacbcccd 3ebfc0c1c2c3c4c5 36b7b8b9babbbcbd 2eafb0b1b2b3b4b5 26a7a8a9aaabacad 1e9fa0a1a2a3a4a5
|
||||||
|
r_dnq: 36f7f8f9fafbfcfd 3eff000102030405 060708090a0b0c0d 0e0f101112131415 161718191a1b1c1d 1e1f202122232425 262728292a2b2c2d 2e2f303132333435 363738393a3b3c3d 3e3f404142434445 064748494a4b4c4d
|
||||||
|
r_upw: a8a9aaabacadaeafb0 9fa0a1a2a3a4a5a6a7 969798999a9b9c9d9e 8d8e8f909192939495 8485868788898a8b8c 7b7c7d7e7f80818283 72737475767778797a 696a6b6c6d6e6f7071 606162636465666768 5758595a5b5c5d5e5f 4e4f50515253545556
|
||||||
|
r_dnw: b1b2b3b4b5b6b7b8b9 babbbcbdbebfc0c1c2 c3c4c5c6c7c8c9cacb cccdcecfd0d1d2d3d4 d5d6d7d8d9dadbdcdd dedfe0e1e2e3e4e5e6 e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8 f9fafbfcfdfeff0001 02030405060708090a 0b0c0d0e0f10111213
|
||||||
|
|
||||||
|
Dump:
|
||||||
|
r_i: ffffffff
|
||||||
|
r_upb: 05 04 03 02 01 00 ff ff ff ff ff
|
||||||
|
r_dnb: ff ff ff ff ff ff ff ff ff ff ff
|
||||||
|
r_ups: 3fff 3fff 3fff 3fff 0809 0607 3fff 3fff 3fff 3fff 3fff
|
||||||
|
r_dns: 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff 3fff
|
||||||
|
r_upi: 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff
|
||||||
|
r_dni: 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff 7fffffff
|
||||||
|
r_upq: 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff
|
||||||
|
r_dnq: 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff 3fffffffffffffff
|
||||||
|
r_upw: ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff
|
||||||
|
r_dnw: ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff ffffffffffffffffff
|
||||||
|
|
||||||
|
*-* All Finished *-*
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2019 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.
|
||||||
|
use IO::File;
|
||||||
|
#use Data::Dumper;
|
||||||
|
use strict;
|
||||||
|
use vars qw($Self);
|
||||||
|
|
||||||
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
|
sub gen {
|
||||||
|
my $filename = shift;
|
||||||
|
|
||||||
|
my $fh = IO::File->new(">$filename");
|
||||||
|
for (my $copy=0; $copy<32; ++$copy) {
|
||||||
|
for (my $i=0; $i<=255; ++$i) {
|
||||||
|
$fh->print(chr($i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gen("$Self->{obj_dir}/t_sys_fread.mem");
|
||||||
|
|
||||||
|
compile(
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2019 by Wilson Snyder.
|
||||||
|
|
||||||
|
`define STRINGIFY(x) `"x`"
|
||||||
|
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
module t;
|
||||||
|
integer file;
|
||||||
|
integer r_i;
|
||||||
|
byte r_upb[20:10];
|
||||||
|
byte r_dnb[20:10];
|
||||||
|
reg [13:0] r_ups[20:10];
|
||||||
|
reg [13:0] r_dns[10:20];
|
||||||
|
reg [30:0] r_upi[20:10];
|
||||||
|
reg [30:0] r_dni[10:20];
|
||||||
|
reg [61:0] r_upq[20:10];
|
||||||
|
reg [61:0] r_dnq[10:20];
|
||||||
|
reg [71:0] r_upw[20:10];
|
||||||
|
reg [71:0] r_dnw[10:20];
|
||||||
|
|
||||||
|
task clear;
|
||||||
|
// Initialize memories to zero,
|
||||||
|
// avoid differences between 2-state and 4-state.
|
||||||
|
r_i = ~0;
|
||||||
|
foreach (r_upb[i]) r_upb[i] = ~0;
|
||||||
|
foreach (r_dnb[i]) r_dnb[i] = ~0;
|
||||||
|
foreach (r_ups[i]) r_ups[i] = ~0;
|
||||||
|
foreach (r_dns[i]) r_dns[i] = ~0;
|
||||||
|
foreach (r_upi[i]) r_upi[i] = ~0;
|
||||||
|
foreach (r_dni[i]) r_dni[i] = ~0;
|
||||||
|
foreach (r_upq[i]) r_upq[i] = ~0;
|
||||||
|
foreach (r_dnq[i]) r_dnq[i] = ~0;
|
||||||
|
foreach (r_upw[i]) r_upw[i] = ~0;
|
||||||
|
foreach (r_dnw[i]) r_dnw[i] = ~0;
|
||||||
|
|
||||||
|
// Open file
|
||||||
|
$fclose(file);
|
||||||
|
file = $fopen({`STRINGIFY(`TEST_OBJ_DIR),"/t_sys_fread.mem"}, "r");
|
||||||
|
if ($feof(file)) $stop;
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task dump;
|
||||||
|
$write("Dump:");
|
||||||
|
$write("\n r_i:"); $write(" %x",r_i);
|
||||||
|
$write("\n r_upb:"); foreach (r_upb[i]) $write(" %x", r_upb[i]);
|
||||||
|
$write("\n r_dnb:"); foreach (r_dnb[i]) $write(" %x", r_dnb[i]);
|
||||||
|
$write("\n r_ups:"); foreach (r_ups[i]) $write(" %x", r_ups[i]);
|
||||||
|
$write("\n r_dns:"); foreach (r_dns[i]) $write(" %x", r_dns[i]);
|
||||||
|
$write("\n r_upi:"); foreach (r_upi[i]) $write(" %x", r_upi[i]);
|
||||||
|
$write("\n r_dni:"); foreach (r_dni[i]) $write(" %x", r_dni[i]);
|
||||||
|
$write("\n r_upq:"); foreach (r_upq[i]) $write(" %x", r_upq[i]);
|
||||||
|
$write("\n r_dnq:"); foreach (r_dnq[i]) $write(" %x", r_dnq[i]);
|
||||||
|
$write("\n r_upw:"); foreach (r_upw[i]) $write(" %x", r_upw[i]);
|
||||||
|
$write("\n r_dnw:"); foreach (r_dnw[i]) $write(" %x", r_dnw[i]);
|
||||||
|
$write("\n\n");
|
||||||
|
endtask
|
||||||
|
|
||||||
|
integer code;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
clear;
|
||||||
|
code = $fread(r_i, file); `checkd(code, 4);
|
||||||
|
code = $fread(r_upb, file); `checkd(code, 11);
|
||||||
|
code = $fread(r_dnb, file); `checkd(code, 11);
|
||||||
|
code = $fread(r_ups, file); `checkd(code, 22);
|
||||||
|
code = $fread(r_dns, file); `checkd(code, 22);
|
||||||
|
code = $fread(r_upi, file); `checkd(code, 44);
|
||||||
|
code = $fread(r_dni, file); `checkd(code, 44);
|
||||||
|
code = $fread(r_upq, file); `checkd(code, 88);
|
||||||
|
code = $fread(r_dnq, file); `checkd(code, 88);
|
||||||
|
code = $fread(r_upw, file); `checkd(code, 99);
|
||||||
|
code = $fread(r_dnw, file); `checkd(code, 99);
|
||||||
|
dump;
|
||||||
|
|
||||||
|
clear;
|
||||||
|
code = $fread(r_upb, file, 15); `checkd(code, 6);
|
||||||
|
code = $fread(r_ups, file, 15, 2); `checkd(code, 4);
|
||||||
|
dump;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue