Support .
This commit is contained in:
parent
fdcbedef8f
commit
d6884db439
2
Changes
2
Changes
|
|
@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
|||
|
||||
*** Support $feof, $fflush. [Holger Waechtler]
|
||||
|
||||
*** Support $random.
|
||||
|
||||
* Verilator 3.665 2008/06/25
|
||||
|
||||
**** Ignore "// verilator" comments alone on endif lines. [Rodney Sinclair]
|
||||
|
|
|
|||
|
|
@ -1569,6 +1569,12 @@ $setup, $setuphold, $skew, $timeskew, $width
|
|||
|
||||
All specify blocks and timing checks are ignored.
|
||||
|
||||
=item $random
|
||||
|
||||
$random does not support the optional argument to set the seed. Use the
|
||||
srand function in C to accomplish this, and note there is only one random
|
||||
number generator (not one per module).
|
||||
|
||||
=item $readmemb, $readmemh
|
||||
|
||||
Read memory commands should work properly. Note Verilator and the Verilog
|
||||
|
|
|
|||
|
|
@ -80,23 +80,43 @@ IData VL_RAND32() {
|
|||
#endif
|
||||
}
|
||||
|
||||
IData VL_RAND_RESET_I(int outBits) {
|
||||
IData VL_RANDOM_I(int obits) {
|
||||
return VL_RAND32() & VL_MASK_I(obits);
|
||||
}
|
||||
|
||||
QData VL_RANDOM_Q(int obits) {
|
||||
QData data = ((QData)VL_RAND32()<<VL_ULL(32)) | (QData)VL_RAND32();
|
||||
return data & VL_MASK_Q(obits);
|
||||
}
|
||||
|
||||
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) {
|
||||
for (int i=0; i<VL_WORDS_I(obits); i++) {
|
||||
if (i<(VL_WORDS_I(obits)-1)) {
|
||||
outwp[i] = VL_RAND32();
|
||||
} else {
|
||||
outwp[i] = VL_RAND32() & VL_MASK_I(obits);
|
||||
}
|
||||
}
|
||||
return outwp;
|
||||
}
|
||||
|
||||
IData VL_RAND_RESET_I(int obits) {
|
||||
if (Verilated::randReset()==0) return 0;
|
||||
IData data = ~0;
|
||||
if (Verilated::randReset()!=1) { // if 2, randomize
|
||||
data = VL_RAND32();
|
||||
data = VL_RANDOM_I(obits);
|
||||
}
|
||||
if (outBits<32) data &= VL_MASK_I(outBits);
|
||||
if (obits<32) data &= VL_MASK_I(obits);
|
||||
return data;
|
||||
}
|
||||
|
||||
QData VL_RAND_RESET_Q(int outBits) {
|
||||
QData VL_RAND_RESET_Q(int obits) {
|
||||
if (Verilated::randReset()==0) return 0;
|
||||
QData data = VL_ULL(~0);
|
||||
if (Verilated::randReset()!=1) { // if 2, randomize
|
||||
data = ((QData)VL_RAND32()<<VL_ULL(32)) | (QData)VL_RAND32();
|
||||
data = VL_RANDOM_Q(obits);
|
||||
}
|
||||
if (outBits<64) data &= VL_MASK_Q(outBits);
|
||||
if (obits<64) data &= VL_MASK_Q(obits);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -179,8 +179,13 @@ extern void vl_fatal (const char* filename, int linenum, const char* hier,
|
|||
const char* msg);
|
||||
|
||||
//=========================================================================
|
||||
// Extern functions -- Init time only, so slow is fine
|
||||
// Extern functions -- Slow path
|
||||
|
||||
extern IData VL_RANDOM_I(int obits); ///< Randomize a signal
|
||||
extern QData VL_RANDOM_Q(int obits); ///< Randomize a signal
|
||||
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
|
||||
|
||||
/// Init time only, so slow is fine
|
||||
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
|
||||
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
|
||||
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
|
||||
|
|
|
|||
|
|
@ -1768,14 +1768,18 @@ struct AstScopeName : public AstNode {
|
|||
|
||||
struct AstRand : public AstNodeTermop {
|
||||
// Return a random number, based upon width()
|
||||
AstRand(FileLine* fl, int wwidth) : AstNodeTermop(fl) {
|
||||
width(wwidth,wwidth); }
|
||||
private:
|
||||
bool m_reset; // Random reset, versus always random
|
||||
public:
|
||||
AstRand(FileLine* fl, int wwidth, bool reset) : AstNodeTermop(fl) {
|
||||
width(wwidth,wwidth); m_reset=reset; }
|
||||
AstRand(FileLine* fl) : AstNodeTermop(fl), m_reset(false) { }
|
||||
virtual ~AstRand() {}
|
||||
virtual AstType type() const { return AstType::RAND;}
|
||||
virtual AstNode* clone() { return new AstRand(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual string emitVerilog() { return "$random"; }
|
||||
virtual string emitOperator() { return "VL_RAND_RESET"; }
|
||||
virtual string emitOperator() { return (m_reset ? "VL_RAND_RESET":"VL_RANDOM"); }
|
||||
virtual bool cleanOut() { return true; }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
|
|
|
|||
|
|
@ -103,6 +103,10 @@ private:
|
|||
virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstNeqWild* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
|
||||
|
||||
//========
|
||||
// Signed: Output signed
|
||||
virtual void visit(AstRand* nodep, AstNUser*) { signed_Os_Ix(nodep); }
|
||||
|
||||
//=======
|
||||
// Signed: Output signed iff LHS signed; unary operator
|
||||
virtual void visit(AstNot* nodep, AstNUser*) { signed_Olhs(nodep); }
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ private:
|
|||
new AstAnd(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(),numbx),
|
||||
new AstRand(nodep->fileline(),
|
||||
nodep->width())))));
|
||||
nodep->width(), true)))));
|
||||
// Add inits in front of other statement.
|
||||
// In the future, we should stuff the initp into the module's constructor.
|
||||
AstNode* afterp = m_modp->stmtsp()->unlinkFrBackWithNext();
|
||||
|
|
|
|||
|
|
@ -362,6 +362,11 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRand* nodep, AstNUser* vup) {
|
||||
if (vup->c()->prelim()) {
|
||||
nodep->width(32,32); // Says the spec
|
||||
}
|
||||
}
|
||||
virtual void visit(AstTime* nodep, AstNUser*) {
|
||||
nodep->width(64,64);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ escid \\[^ \t\f\r\n]+
|
|||
"$hold" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
|
||||
"$nochange" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
|
||||
"$period" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
|
||||
"$random" {yylval.fileline = CRELINE(); return yD_RANDOM;}
|
||||
"$readmemb" {yylval.fileline = CRELINE(); return yD_READMEMB;}
|
||||
"$readmemh" {yylval.fileline = CRELINE(); return yD_READMEMH;}
|
||||
"$realtime" {yylval.fileline = CRELINE(); return yD_TIME;}
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ class AstSenTree;
|
|||
%token<fileline> yD_ISUNKNOWN "$isunknown"
|
||||
%token<fileline> yD_ONEHOT "$onehot"
|
||||
%token<fileline> yD_ONEHOT0 "$onehot0"
|
||||
%token<fileline> yD_RANDOM "$random"
|
||||
%token<fileline> yD_READMEMB "$readmemb"
|
||||
%token<fileline> yD_READMEMH "$readmemh"
|
||||
%token<fileline> yD_SIGNED "$signed"
|
||||
|
|
@ -1085,6 +1086,9 @@ exprNoStr: expr yP_OROR expr { $$ = new AstLogOr ($2,$1,$3); }
|
|||
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
|
||||
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
|
||||
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
|
||||
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")\n"); }
|
||||
| yD_RANDOM '(' ')' { $$ = new AstRand($1); }
|
||||
| yD_RANDOM { $$ = new AstRand($1); }
|
||||
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
|
||||
| yD_TIME { $$ = new AstTime($1); }
|
||||
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2008 by Wilson Snyder.
|
||||
|
||||
module t;
|
||||
|
||||
reg [31:0] lastrand;
|
||||
reg [31:0] thisrand;
|
||||
|
||||
integer same = 0;
|
||||
integer i;
|
||||
|
||||
`define TRIES 20
|
||||
|
||||
initial begin
|
||||
// There's a 1^32 chance of the numbers being the same twice,
|
||||
// so we'll allow one failure
|
||||
lastrand = $random;
|
||||
for (i=0; i<`TRIES; i=i+1) begin
|
||||
thisrand = $random;
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("Random = %x\n", thisrand);
|
||||
`endif
|
||||
if (thisrand == lastrand) same=same+1;
|
||||
lastrand = thisrand;
|
||||
end
|
||||
if (same > 1) begin
|
||||
$write("%%Error: Too many similar numbers: %d\n", same);
|
||||
$stop;
|
||||
end
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
Loading…
Reference in New Issue