mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Add the support of UDP table for the nonsequential logic.
This commit is contained in:
parent
676fd31635
commit
cb04ebafc3
@ -177,6 +177,7 @@ set(HEADERS
|
|||||||
V3Trace.h
|
V3Trace.h
|
||||||
V3TraceDecl.h
|
V3TraceDecl.h
|
||||||
V3Tristate.h
|
V3Tristate.h
|
||||||
|
V3Udp.h
|
||||||
V3Undriven.h
|
V3Undriven.h
|
||||||
V3UniqueNames.h
|
V3UniqueNames.h
|
||||||
V3Unknown.h
|
V3Unknown.h
|
||||||
@ -324,6 +325,7 @@ set(COMMON_SOURCES
|
|||||||
V3TraceDecl.cpp
|
V3TraceDecl.cpp
|
||||||
V3Tristate.cpp
|
V3Tristate.cpp
|
||||||
V3TSP.cpp
|
V3TSP.cpp
|
||||||
|
V3Udp.cpp
|
||||||
V3Undriven.cpp
|
V3Undriven.cpp
|
||||||
V3Unknown.cpp
|
V3Unknown.cpp
|
||||||
V3Unroll.cpp
|
V3Unroll.cpp
|
||||||
|
@ -310,6 +310,7 @@ RAW_OBJS_PCH_ASTNOMT = \
|
|||||||
V3Trace.o \
|
V3Trace.o \
|
||||||
V3TraceDecl.o \
|
V3TraceDecl.o \
|
||||||
V3Tristate.o \
|
V3Tristate.o \
|
||||||
|
V3Udp.o \
|
||||||
V3Undriven.o \
|
V3Undriven.o \
|
||||||
V3Unknown.o \
|
V3Unknown.o \
|
||||||
V3Unroll.o \
|
V3Unroll.o \
|
||||||
|
@ -444,6 +444,7 @@ public:
|
|||||||
bool isBitLogic() const { return keyword().isBitLogic(); }
|
bool isBitLogic() const { return keyword().isBitLogic(); }
|
||||||
bool isDouble() const VL_MT_STABLE { return keyword().isDouble(); }
|
bool isDouble() const VL_MT_STABLE { return keyword().isDouble(); }
|
||||||
bool isEvent() const VL_MT_STABLE { return keyword() == VBasicDTypeKwd::EVENT; }
|
bool isEvent() const VL_MT_STABLE { return keyword() == VBasicDTypeKwd::EVENT; }
|
||||||
|
bool isLogic() const VL_MT_STABLE { return keyword() == VBasicDTypeKwd::LOGIC; }
|
||||||
bool isTriggerVec() const VL_MT_SAFE { return keyword() == VBasicDTypeKwd::TRIGGERVEC; }
|
bool isTriggerVec() const VL_MT_SAFE { return keyword() == VBasicDTypeKwd::TRIGGERVEC; }
|
||||||
bool isForkSync() const VL_MT_SAFE { return keyword() == VBasicDTypeKwd::FORK_SYNC; }
|
bool isForkSync() const VL_MT_SAFE { return keyword() == VBasicDTypeKwd::FORK_SYNC; }
|
||||||
bool isProcessRef() const VL_MT_SAFE { return keyword() == VBasicDTypeKwd::PROCESS_REFERENCE; }
|
bool isProcessRef() const VL_MT_SAFE { return keyword() == VBasicDTypeKwd::PROCESS_REFERENCE; }
|
||||||
|
@ -1784,13 +1784,24 @@ public:
|
|||||||
ASTGEN_MEMBERS_AstUdpTable;
|
ASTGEN_MEMBERS_AstUdpTable;
|
||||||
};
|
};
|
||||||
class AstUdpTableLine final : public AstNode {
|
class AstUdpTableLine final : public AstNode {
|
||||||
|
// @astgen op1 := ifieldp : List[AstUdpTableLineVal]
|
||||||
|
// @astgen op2 := ofieldp : List[AstUdpTableLineVal]
|
||||||
|
public:
|
||||||
|
AstUdpTableLine(FileLine* fl, AstUdpTableLineVal* ifieldp, AstUdpTableLineVal* ofieldp)
|
||||||
|
: ASTGEN_SUPER_UdpTableLine(fl) {
|
||||||
|
this->addIfieldp(ifieldp);
|
||||||
|
this->addOfieldp(ofieldp);
|
||||||
|
}
|
||||||
|
ASTGEN_MEMBERS_AstUdpTableLine;
|
||||||
|
};
|
||||||
|
class AstUdpTableLineVal final : public AstNode {
|
||||||
string m_text;
|
string m_text;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AstUdpTableLine(FileLine* fl, const string& text)
|
AstUdpTableLineVal(FileLine* fl, const string& text)
|
||||||
: ASTGEN_SUPER_UdpTableLine(fl)
|
: ASTGEN_SUPER_UdpTableLineVal(fl)
|
||||||
, m_text{text} {}
|
, m_text{text} {}
|
||||||
ASTGEN_MEMBERS_AstUdpTableLine;
|
ASTGEN_MEMBERS_AstUdpTableLineVal;
|
||||||
string name() const override VL_MT_STABLE { return m_text; }
|
string name() const override VL_MT_STABLE { return m_text; }
|
||||||
string text() const VL_MT_SAFE { return m_text; }
|
string text() const VL_MT_SAFE { return m_text; }
|
||||||
};
|
};
|
||||||
|
@ -112,8 +112,8 @@ class InstVisitor final : public VNVisitor {
|
|||||||
void visit(AstUdpTable* nodep) override {
|
void visit(AstUdpTable* nodep) override {
|
||||||
if (!v3Global.opt.bboxUnsup()) {
|
if (!v3Global.opt.bboxUnsup()) {
|
||||||
// If we support primitives, update V3Undriven to remove special case
|
// If we support primitives, update V3Undriven to remove special case
|
||||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Verilog 1995 UDP Tables. "
|
//nodep->v3warn(E_UNSUPPORTED, "Unsupported: Verilog 1995 UDP Tables. "
|
||||||
"Use --bbox-unsup to ignore tables.");
|
// "Use --bbox-unsup to ignore tables.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
204
src/V3Udp.cpp
Normal file
204
src/V3Udp.cpp
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Implementation of Christofides algorithm to
|
||||||
|
// approximate the solution to the traveling salesman problem.
|
||||||
|
//
|
||||||
|
// ISSUES: This isn't exactly Christofides algorithm; see the TODO
|
||||||
|
// in perfectMatching(). True minimum-weight perfect matching
|
||||||
|
// would produce a better result. How much better is TBD.
|
||||||
|
//
|
||||||
|
// Code available from: https://verilator.org
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2024 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.
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
|
||||||
|
|
||||||
|
#include "V3Udp.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
|
|
||||||
|
//V3Udp add the support for UDP table.
|
||||||
|
// For example:
|
||||||
|
// table
|
||||||
|
// x 0 1 : 1;
|
||||||
|
// 0 ? 1 : 1;
|
||||||
|
// 0 1 0 : 0;
|
||||||
|
// endtable
|
||||||
|
// For every table line, for the input field,
|
||||||
|
// two number (mask number and compare number) will
|
||||||
|
// be generated to help make a judegement whether
|
||||||
|
// the input field condition is satisfied. For example,
|
||||||
|
// for line x 0 1 : 1, mask = 011 cmp = 001, the condition
|
||||||
|
// is mask & inputvar == cmp. This passed should be added
|
||||||
|
// before V3Inline and V3Tristate.
|
||||||
|
|
||||||
|
class UdpVisitor final : public VNVisitor {
|
||||||
|
AstVar* m_ifieldVarp = nullptr; // input field var of table line.
|
||||||
|
AstVar* m_ofieldVarp = nullptr; // output filed var of table line.
|
||||||
|
std::vector<AstVar*> m_inputVars; // All the input vars in the AstPrimitive.
|
||||||
|
std::vector<AstVar*> m_outputVars; // All the output vars in the AstPrimitive.
|
||||||
|
AstPrimitive* m_primp = nullptr;
|
||||||
|
AstIf* m_lineStmtp = nullptr; // stmt for every line in UDP Table.
|
||||||
|
AstAlways* m_alwaysp = nullptr; // UPD Table is realized under the always_latch.
|
||||||
|
bool m_isFirstOutput = false; // Whether the first IO port is output.
|
||||||
|
int m_inputNum = 0;
|
||||||
|
int m_outputNum = 0;
|
||||||
|
|
||||||
|
void visit(AstPrimitive* nodep) override {
|
||||||
|
m_primp = nodep;
|
||||||
|
m_isFirstOutput = false;
|
||||||
|
m_inputVars.clear();
|
||||||
|
m_outputVars.clear();
|
||||||
|
iterateChildren(nodep);
|
||||||
|
m_primp = nullptr;
|
||||||
|
}
|
||||||
|
void visit(AstVar* nodep) override {
|
||||||
|
// Push the input and output vars for primitive.
|
||||||
|
if (m_primp) {
|
||||||
|
if (nodep->isIO()) {
|
||||||
|
if (nodep->isInput()) {
|
||||||
|
m_inputVars.push_back(nodep);
|
||||||
|
} else {
|
||||||
|
m_outputVars.push_back(nodep);
|
||||||
|
}
|
||||||
|
if ((m_inputVars.size() == 0) && (m_outputVars.size() == 1)) {
|
||||||
|
m_isFirstOutput = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iterateChildren(nodep);
|
||||||
|
}
|
||||||
|
void visit(AstUdpTable* nodep) override {
|
||||||
|
auto fl = nodep->fileline();
|
||||||
|
m_lineStmtp = nullptr;
|
||||||
|
m_inputNum = m_inputVars.size();
|
||||||
|
m_outputNum = m_outputVars.size();
|
||||||
|
if (m_outputNum != 1) {
|
||||||
|
m_outputVars.back()->v3error(
|
||||||
|
m_outputNum << " output ports for udp table, there must be one output port!");
|
||||||
|
}
|
||||||
|
if (!m_isFirstOutput && m_outputNum) {
|
||||||
|
m_inputVars[0]->v3error("The first port must be the output port!");
|
||||||
|
}
|
||||||
|
m_ofieldVarp = m_outputVars[0];
|
||||||
|
AstBasicDType* const bdtypep = VN_CAST(m_ofieldVarp->childDTypep(), BasicDType);
|
||||||
|
if (bdtypep && bdtypep->isLogic()) { // If output is reg.
|
||||||
|
bdtypep->v3error("sequetial UDP is not suppoted currently!");
|
||||||
|
}
|
||||||
|
// Input var for the ifield,
|
||||||
|
// add the input filed var and corresponding varref.
|
||||||
|
AstNodeDType* const typep = nodep->findBitDType(m_inputNum, m_inputNum, VSigning::NOSIGN);
|
||||||
|
m_ifieldVarp = new AstVar{fl, VVarType::MODULETEMP, "tableline__ifield__udptmp", typep};
|
||||||
|
m_inputVars.back()->addNextHere(m_ifieldVarp);
|
||||||
|
AstVarRef* const ifieldRefp = new AstVarRef{fl, m_ifieldVarp, VAccess::WRITE};
|
||||||
|
auto itr = m_inputVars.begin();
|
||||||
|
// relate the input vars with the input field var by concat
|
||||||
|
AstNodeExpr* contactp = new AstVarRef{fl, *itr, VAccess::READ};
|
||||||
|
while (++itr != m_inputVars.end()) {
|
||||||
|
contactp = new AstConcat{fl, new AstVarRef{fl, *itr, VAccess::READ}, contactp};
|
||||||
|
}
|
||||||
|
AstNodeStmt* const ifieldStmtp = new AstAssignW{fl, ifieldRefp, contactp};
|
||||||
|
// Use the always_latch to realize the UDP table.
|
||||||
|
m_alwaysp = new AstAlways{fl, VAlwaysKwd::ALWAYS, nullptr, nullptr};
|
||||||
|
ifieldStmtp->addNextHere(m_alwaysp);
|
||||||
|
// Output var for the ofield
|
||||||
|
iterateChildren(nodep);
|
||||||
|
nodep->replaceWith(ifieldStmtp);
|
||||||
|
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||||
|
}
|
||||||
|
void visit(AstUdpTableLine* nodep) override {
|
||||||
|
auto fl = nodep->fileline();
|
||||||
|
AstNode* inodep = nodep->ifieldp();
|
||||||
|
AstNode* onodep = nodep->ofieldp();
|
||||||
|
std::vector<AstUdpTableLineVal*> ifieldNodes;
|
||||||
|
std::vector<AstUdpTableLineVal*> ofieldNodes;
|
||||||
|
while (inodep) {
|
||||||
|
if (AstUdpTableLineVal* linevalp = VN_CAST(inodep, UdpTableLineVal)) {
|
||||||
|
ifieldNodes.push_back(linevalp);
|
||||||
|
}
|
||||||
|
inodep = inodep->nextp();
|
||||||
|
}
|
||||||
|
if (ifieldNodes.size() != m_inputNum) {
|
||||||
|
nodep->v3error(m_inputNum << " input val required, while there are "
|
||||||
|
<< ifieldNodes.size() << " input for the table line!");
|
||||||
|
}
|
||||||
|
while (onodep) {
|
||||||
|
if (AstUdpTableLineVal* linevalp = VN_CAST(onodep, UdpTableLineVal)) {
|
||||||
|
ofieldNodes.push_back(linevalp);
|
||||||
|
}
|
||||||
|
onodep = onodep->nextp();
|
||||||
|
}
|
||||||
|
// Build the ifield condition
|
||||||
|
// For one table line, the match condition is
|
||||||
|
// ifieldRefp & maskNum == cmpNum
|
||||||
|
// For example: 0?1:1
|
||||||
|
// maskNum is : 101
|
||||||
|
// cmpNum is : 001
|
||||||
|
V3Number maskNum{nodep, m_inputNum};
|
||||||
|
V3Number cmpNum{nodep, m_inputNum};
|
||||||
|
int bitIndex = 0;
|
||||||
|
for (auto ivalp : ifieldNodes) {
|
||||||
|
std::string bitval = ivalp->name().substr(0, 1);
|
||||||
|
if (bitval == "0") {
|
||||||
|
maskNum.setBit(bitIndex, 1);
|
||||||
|
cmpNum.setBit(bitIndex, 0);
|
||||||
|
} else if (bitval == "1") {
|
||||||
|
maskNum.setBit(bitIndex, 1);
|
||||||
|
cmpNum.setBit(bitIndex, 1);
|
||||||
|
} else {
|
||||||
|
maskNum.setBit(bitIndex, 0);
|
||||||
|
cmpNum.setBit(bitIndex, 0);
|
||||||
|
}
|
||||||
|
bitIndex++;
|
||||||
|
}
|
||||||
|
AstConst* const maskConstp = new AstConst{fl, maskNum};
|
||||||
|
AstConst* const cmpConstp = new AstConst{fl, cmpNum};
|
||||||
|
AstNodeExpr* const condExprp = new AstEq{
|
||||||
|
fl, new AstAnd{fl, maskConstp, new AstVarRef{fl, m_ifieldVarp, VAccess::READ}},
|
||||||
|
cmpConstp};
|
||||||
|
//Build the ofield val
|
||||||
|
V3Number onum{nodep, 1};
|
||||||
|
auto ovalp = ofieldNodes[0];
|
||||||
|
std::string bitval = ovalp->name().substr(0, 1);
|
||||||
|
if (bitval == "0") {
|
||||||
|
onum.setBit(0, 0);
|
||||||
|
} else if (bitval == "1") {
|
||||||
|
onum.setBit(0, 1);
|
||||||
|
} else {
|
||||||
|
onum.setBit(0, 'x');
|
||||||
|
}
|
||||||
|
//Build the whole field line stmt.
|
||||||
|
AstAssign* const thenStmtp = new AstAssign{
|
||||||
|
fl, new AstVarRef{fl, m_ofieldVarp, VAccess::WRITE}, new AstConst{fl, onum}};
|
||||||
|
AstIf* const ifStmtp = new AstIf{fl, condExprp, thenStmtp};
|
||||||
|
if (!m_lineStmtp) {
|
||||||
|
m_lineStmtp = ifStmtp;
|
||||||
|
m_alwaysp->addStmtsp(m_lineStmtp);
|
||||||
|
} else {
|
||||||
|
m_lineStmtp->addElsesp(ifStmtp);
|
||||||
|
m_lineStmtp = ifStmtp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CONSTRUCTORS
|
||||||
|
explicit UdpVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||||
|
~UdpVisitor() override = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
void V3Udp::udpResolve(AstNetlist* rootp) {
|
||||||
|
UINFO(4, __FUNCTION__ << ": " << endl);
|
||||||
|
{ const UdpVisitor visitor{rootp}; } // Destruct before checking
|
||||||
|
V3Global::dumpCheckGlobalTree("udpResolve", 0, dumpTreeEitherLevel() >= 3);
|
||||||
|
}
|
32
src/V3Udp.h
Normal file
32
src/V3Udp.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Replace return/continue with jumps
|
||||||
|
//
|
||||||
|
// Code available from: https://verilator.org
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2024 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.
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#ifndef VERILATOR_V3UDP_H_
|
||||||
|
#define VERILATOR_V3UDP_H_
|
||||||
|
|
||||||
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
|
||||||
|
class AstNetlist;
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
class V3Udp final {
|
||||||
|
public:
|
||||||
|
static void udpResolve(AstNetlist* rootp) VL_MT_DISABLED;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // Guard
|
@ -101,6 +101,7 @@
|
|||||||
#include "V3Trace.h"
|
#include "V3Trace.h"
|
||||||
#include "V3TraceDecl.h"
|
#include "V3TraceDecl.h"
|
||||||
#include "V3Tristate.h"
|
#include "V3Tristate.h"
|
||||||
|
#include "V3Udp.h"
|
||||||
#include "V3Undriven.h"
|
#include "V3Undriven.h"
|
||||||
#include "V3Unknown.h"
|
#include "V3Unknown.h"
|
||||||
#include "V3Unroll.h"
|
#include "V3Unroll.h"
|
||||||
@ -184,6 +185,8 @@ static void process() {
|
|||||||
V3Dead::deadifyModules(v3Global.rootp());
|
V3Dead::deadifyModules(v3Global.rootp());
|
||||||
v3Global.checkTree();
|
v3Global.checkTree();
|
||||||
|
|
||||||
|
V3Udp::udpResolve(v3Global.rootp());
|
||||||
|
|
||||||
// Create a hierarchical Verilation plan
|
// Create a hierarchical Verilation plan
|
||||||
if (!v3Global.opt.lintOnly() && !v3Global.opt.serializeOnly()
|
if (!v3Global.opt.lintOnly() && !v3Global.opt.serializeOnly()
|
||||||
&& v3Global.opt.hierarchical()) {
|
&& v3Global.opt.hierarchical()) {
|
||||||
|
@ -390,7 +390,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||||||
"strong1" { FL; return ySTRONG1; }
|
"strong1" { FL; return ySTRONG1; }
|
||||||
"supply0" { FL; return ySUPPLY0; }
|
"supply0" { FL; return ySUPPLY0; }
|
||||||
"supply1" { FL; return ySUPPLY1; }
|
"supply1" { FL; return ySUPPLY1; }
|
||||||
"table" { FL; yy_push_state(TABLE); return yTABLE; }
|
"table"[ \t]* { FL; yy_push_state(TABLE); return yTABLE; }
|
||||||
"task" { FL; return yTASK; }
|
"task" { FL; return yTASK; }
|
||||||
"time" { FL; return yTIME; }
|
"time" { FL; return yTIME; }
|
||||||
"tran" { FL; return yTRAN; }
|
"tran" { FL; return yTRAN; }
|
||||||
@ -1007,18 +1007,21 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Attributes */
|
/* Attributes */
|
||||||
/* Note simulators vary in support for "(* /_*something*_/ foo*)" where _ doesn't exist */
|
/* Note simulators vary in support for "(* /_*something*_/ foo*)" where _ doesn't exist */
|
||||||
<V95,V01NC,V01C,V05,VA5,S05,S09,S12,S17,S23,SAX>{
|
<V95,V01NC,V01C,V05,VA5,S05,S09,S12,S17,S23,SAX,TABLE>{
|
||||||
"(*"({ws}|{crnl})*({id}|{escid}) { yymore(); yy_push_state(ATTRMODE); } /* Doesn't match (*), but (* attr_spec */
|
"(*"({ws}|{crnl})*({id}|{escid}) { yymore(); yy_push_state(ATTRMODE); } /* Doesn't match (*), but (* attr_spec */
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Tables */
|
/* Tables */
|
||||||
<TABLE>\\{crnl} { yymore(); }
|
<TABLE>[01xX\?] {FL; yylval.strp = PARSEP->newString(yytext, yyleng); return yaTABLEIFIELDVAL; } /* Input field symbol. */
|
||||||
<TABLE>{crnl} { yymore(); }
|
<TABLE>[ \t]+ { FL; return yaTABLESEP; } /* Separator for table line. */
|
||||||
<TABLE>";" { FL; yylval.strp = PARSEP->newString(yytext, yyleng); return yaTABLELINE; }
|
<TABLE>[ \t]*[\\]+[ \t]*[\n][ \t]* { FL; return yaTABLELSEP; } /* Separator for table line. */
|
||||||
<TABLE>"endtable" { yy_pop_state(); FL; return yENDTABLE; }
|
<TABLE>[:] { FL; return yaTABLELRSEP; } /* LHS and RHS separator for table line. */
|
||||||
|
<TABLE>[ \t]*[;][ \t]* { FL; return yaTABLELINEEND; }
|
||||||
|
<TABLE>[\r\n] { FL_FWD; FL_BRK; }
|
||||||
<TABLE>"`line"{ws}+[^\n\r]*{crnl} { FL_FWD; PARSEP->lexPpline(yytext); FL_BRK; }
|
<TABLE>"`line"{ws}+[^\n\r]*{crnl} { FL_FWD; PARSEP->lexPpline(yytext); FL_BRK; }
|
||||||
<TABLE>. { yymore(); }
|
<TABLE>^[ \t]*[\r\n] { FL_FWD; FL_BRK; }
|
||||||
|
<TABLE>[ \t]*"endtable"[ \t\f]*[\n\r] { yy_pop_state(); FL; return yENDTABLE; }
|
||||||
<TABLE><<EOF>> { FL; yylval.fl->v3error("EOF in 'table'");
|
<TABLE><<EOF>> { FL; yylval.fl->v3error("EOF in 'table'");
|
||||||
yyleng = 0; yy_pop_state(); FL_BRK; yyterminate(); }
|
yyleng = 0; yy_pop_state(); FL_BRK; yyterminate(); }
|
||||||
|
|
||||||
|
@ -448,6 +448,12 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
|
|||||||
%token<fl> ygenSTRENGTH "STRENGTH keyword (strong1/etc)"
|
%token<fl> ygenSTRENGTH "STRENGTH keyword (strong1/etc)"
|
||||||
|
|
||||||
%token<strp> yaTABLELINE "TABLE LINE"
|
%token<strp> yaTABLELINE "TABLE LINE"
|
||||||
|
%token<strp> yaTABLEIFIELDVAL "Table_line_input_field_value"
|
||||||
|
%token<strp> yaTABLEOFIELDVAL "Table_line_output_field_value"
|
||||||
|
%token<fl> yaTABLELRSEP ":"
|
||||||
|
%token<fl> yaTABLESEP "Table_line_input_field_value_sep"
|
||||||
|
%token<fl> yaTABLELSEP "Table_line_input_line_field_value_sep"
|
||||||
|
%token<fl> yaTABLELINEEND "Table_line_end"
|
||||||
|
|
||||||
%token<strp> yaSCHDR "`systemc_header BLOCK"
|
%token<strp> yaSCHDR "`systemc_header BLOCK"
|
||||||
%token<strp> yaSCINT "`systemc_ctor BLOCK"
|
%token<strp> yaSCINT "`systemc_ctor BLOCK"
|
||||||
@ -5728,16 +5734,36 @@ combinational_body<nodep>: // IEEE: combinational_body + sequential_body
|
|||||||
yTABLE tableEntryList yENDTABLE { $$ = new AstUdpTable{$1, $2}; }
|
yTABLE tableEntryList yENDTABLE { $$ = new AstUdpTable{$1, $2}; }
|
||||||
;
|
;
|
||||||
|
|
||||||
tableEntryList<udpTableLinep>: // IEEE: { combinational_entry | sequential_entry }
|
tableEntryList<udpTableLinep>: // IEEE: { combinational_entry }
|
||||||
tableEntry { $$ = $1; }
|
tableEntry { $$ = $1; }
|
||||||
| tableEntryList tableEntry { $$ = addNextNull($1, $2); }
|
| tableEntryList tableEntry { $$ = addNextNull($1, $2); }
|
||||||
;
|
;
|
||||||
|
|
||||||
tableEntry<udpTableLinep>: // IEEE: combinational_entry + sequential_entry
|
tableEntry<udpTableLinep>: // IEEE: combinational_entry
|
||||||
yaTABLELINE { $$ = new AstUdpTableLine{$<fl>1, *$1}; }
|
tableLine { $$ = $1; }
|
||||||
| error { $$ = nullptr; }
|
| error { $$ = nullptr; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
tableLine<udpTableLinep>:
|
||||||
|
tableIField yaTABLELRSEP tableOField yaTABLELINEEND { $$ = new AstUdpTableLine{$<fl>1, $1, $3}; }
|
||||||
|
;
|
||||||
|
|
||||||
|
tableIField<udpTableLineValp>:
|
||||||
|
yaTABLESEP tablelVal { $$ = $2; }
|
||||||
|
| tablelVal yaTABLESEP { $$ = $1; }
|
||||||
|
| yaTABLESEP tablelVal yaTABLESEP { $$ = $2; }
|
||||||
|
| tableIField tablelVal yaTABLESEP { $$ = addNextNull($1, $2); }
|
||||||
|
| tableIField tablelVal yaTABLELSEP { $$ = addNextNull($1, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
tablelVal<udpTableLineValp>:
|
||||||
|
yaTABLEIFIELDVAL { $$ = new AstUdpTableLineVal{$<fl>1, *$1}; }
|
||||||
|
;
|
||||||
|
|
||||||
|
tableOField<udpTableLineValp>:
|
||||||
|
yaTABLESEP yaTABLEIFIELDVAL { $$ = new AstUdpTableLineVal{$<fl>2, *$2}; }
|
||||||
|
;
|
||||||
|
|
||||||
//************************************************
|
//************************************************
|
||||||
// Specify
|
// Specify
|
||||||
|
|
||||||
|
@ -9,11 +9,10 @@
|
|||||||
|
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt')
|
test.scenarios('simulator')
|
||||||
test.top_filename = "t/t_udp.v"
|
|
||||||
|
|
||||||
test.lint(
|
test.compile()
|
||||||
# Unsupported: UDP Tables
|
|
||||||
verilator_flags2=["--lint-only --bbox-unsup"])
|
test.execute()
|
||||||
|
|
||||||
test.passes()
|
test.passes()
|
70
test_regress/t/t_nonsequential_udp.v
Executable file
70
test_regress/t/t_nonsequential_udp.v
Executable file
@ -0,0 +1,70 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2015 by Mike Thyer.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
reg a, b, sel, z;
|
||||||
|
udp_mux2(z, a, b, sel);
|
||||||
|
|
||||||
|
int cycle=0;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
cycle <= cycle+1;
|
||||||
|
if (cycle==0) begin
|
||||||
|
a = 0;
|
||||||
|
b = 1;
|
||||||
|
sel = 0;
|
||||||
|
end
|
||||||
|
else if (cycle==1) begin
|
||||||
|
a = 1;
|
||||||
|
b = 1;
|
||||||
|
sel = 0;
|
||||||
|
if (z != 0) $stop;
|
||||||
|
end
|
||||||
|
else if (cycle==2) begin
|
||||||
|
a = 0;
|
||||||
|
b = 1;
|
||||||
|
sel = 0;
|
||||||
|
if (z != 1) $stop;
|
||||||
|
end
|
||||||
|
else if (cycle==3) begin
|
||||||
|
a = 1;
|
||||||
|
b = 0;
|
||||||
|
sel = 0;
|
||||||
|
if (z != 0) $stop;
|
||||||
|
end
|
||||||
|
else if (cycle==4) begin
|
||||||
|
if (z != 1) $stop;
|
||||||
|
end
|
||||||
|
else if (cycle >= 5) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
primitive udp_mux2 (z, a, b, sel);
|
||||||
|
output z;
|
||||||
|
input a, b, sel;
|
||||||
|
table
|
||||||
|
//a b s o
|
||||||
|
? 1 1 : 1 ;
|
||||||
|
? 0 1 : 0 ;
|
||||||
|
1 ? 0 : 1 ;
|
||||||
|
0 ? 0 : 0 ;
|
||||||
|
1 1 x : 1 ;
|
||||||
|
// Next blank line is intentional for parser
|
||||||
|
|
||||||
|
// Next \ at EOL is intentional for parser
|
||||||
|
0 0 x \
|
||||||
|
: 0 ;
|
||||||
|
endtable
|
||||||
|
endprimitive
|
||||||
|
|
||||||
|
|
@ -1,5 +1,100 @@
|
|||||||
%Error-UNSUPPORTED: t/t_udp.v:104:4: Unsupported: Verilog 1995 UDP Tables. Use --bbox-unsup to ignore tables.
|
%Error: t/t_udp.v:124:18: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
104 | table
|
124 | 0 1 : ? : 1;
|
||||||
| ^~~~~
|
| ^
|
||||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
%Error: t/t_udp.v:125:18: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
125 | 0 0 : ? : 0;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:126:18: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
126 | 1 ? : ? : -;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:126:21: Missing verilog.l rule: Default rule invoked in state 13 '-'
|
||||||
|
126 | 1 ? : ? : -;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:136:7: Missing verilog.l rule: Default rule invoked in state 13 'r'
|
||||||
|
136 | r 0 1 ? : ? : 0 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:136:24: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
136 | r 0 1 ? : ? : 0 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:137:7: Missing verilog.l rule: Default rule invoked in state 13 'r'
|
||||||
|
137 | r 1 ? 1 : ? : 1 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:137:24: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
137 | r 1 ? 1 : ? : 1 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:138:7: Missing verilog.l rule: Default rule invoked in state 13 '*'
|
||||||
|
138 | * 1 ? 1 : 1 : 1 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:138:24: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
138 | * 1 ? 1 : 1 : 1 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:139:7: Missing verilog.l rule: Default rule invoked in state 13 '*'
|
||||||
|
139 | * 0 1 ? : 0 : 0 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:139:24: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
139 | * 0 1 ? : 0 : 0 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:140:7: Missing verilog.l rule: Default rule invoked in state 13 'f'
|
||||||
|
140 | f ? ? ? : ? : - ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:140:24: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
140 | f ? ? ? : ? : - ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:140:27: Missing verilog.l rule: Default rule invoked in state 13 '-'
|
||||||
|
140 | f ? ? ? : ? : - ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:141:7: Missing verilog.l rule: Default rule invoked in state 13 'b'
|
||||||
|
141 | b * ? ? : ? : - ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:141:12: Missing verilog.l rule: Default rule invoked in state 13 '*'
|
||||||
|
141 | b * ? ? : ? : - ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:141:24: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
141 | b * ? ? : ? : - ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:141:27: Missing verilog.l rule: Default rule invoked in state 13 '-'
|
||||||
|
141 | b * ? ? : ? : - ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:142:24: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
142 | ? ? 0 ? : ? : 1 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:143:7: Missing verilog.l rule: Default rule invoked in state 13 'b'
|
||||||
|
143 | b ? * 1 : 1 : 1 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:143:15: Missing verilog.l rule: Default rule invoked in state 13 '*'
|
||||||
|
143 | b ? * 1 : 1 : 1 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:143:16: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_input_field_value or :
|
||||||
|
143 | b ? * 1 : 1 : 1 ;
|
||||||
|
| ^~
|
||||||
|
%Error: t/t_udp.v:143:24: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
143 | b ? * 1 : 1 : 1 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:144:15: Missing verilog.l rule: Default rule invoked in state 13 '*'
|
||||||
|
144 | x 1 * 1 : 1 : 1 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:144:16: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_input_field_value or :
|
||||||
|
144 | x 1 * 1 : 1 : 1 ;
|
||||||
|
| ^~
|
||||||
|
%Error: t/t_udp.v:144:24: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
144 | x 1 * 1 : 1 : 1 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:145:24: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_end
|
||||||
|
145 | ? ? 1 0 : ? : 0 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:146:7: Missing verilog.l rule: Default rule invoked in state 13 'b'
|
||||||
|
146 | b ? 1 * : 0 : 0 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:146:18: Missing verilog.l rule: Default rule invoked in state 13 '*'
|
||||||
|
146 | b ? 1 * : 0 : 0 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:146:19: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_input_field_value or :
|
||||||
|
146 | b ? 1 * : 0 : 0 ;
|
||||||
|
| ^~
|
||||||
|
%Error: t/t_udp.v:147:18: Missing verilog.l rule: Default rule invoked in state 13 '*'
|
||||||
|
147 | x 0 1 * : 0 : 0 ;
|
||||||
|
| ^
|
||||||
|
%Error: t/t_udp.v:147:19: syntax error, unexpected Table_line_input_field_value_sep, expecting Table_line_input_field_value or :
|
||||||
|
147 | x 0 1 * : 0 : 0 ;
|
||||||
|
| ^~
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
5
test_regress/t/t_udp_bad_fist_input.out
Normal file
5
test_regress/t/t_udp_bad_fist_input.out
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
%Error: t/t_udp_bad_fist_input.v:8:7: The first port must be the output port!
|
||||||
|
: ... note: In instance 'top'
|
||||||
|
8 | input a, b, c;
|
||||||
|
| ^
|
||||||
|
%Error: Exiting due to
|
16
test_regress/t/t_udp_bad_fist_input.py
Executable file
16
test_regress/t/t_udp_bad_fist_input.py
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 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.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('linter')
|
||||||
|
|
||||||
|
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
test.passes()
|
25
test_regress/t/t_udp_bad_fist_input.v
Executable file
25
test_regress/t/t_udp_bad_fist_input.v
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
primitive t_gate(a, b, c, dout);
|
||||||
|
input a, b, c;
|
||||||
|
output dout;
|
||||||
|
|
||||||
|
table
|
||||||
|
x 0 1 : 1;
|
||||||
|
0 ? 1 : 1;
|
||||||
|
0 1 0 : 0;
|
||||||
|
1 1 ? : 1;
|
||||||
|
1 0 0 : 0;
|
||||||
|
0 0 0 : 1;
|
||||||
|
|
||||||
|
endtable
|
||||||
|
endprimitive
|
||||||
|
module top (a, b, c, o);
|
||||||
|
input a, b, c;
|
||||||
|
output o;
|
||||||
|
t_gate(a, b, c, o);
|
||||||
|
endmodule
|
5
test_regress/t/t_udp_bad_input_num.out
Normal file
5
test_regress/t/t_udp_bad_input_num.out
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
%Error: t/t_udp_bad_input_num.v:14:1: 3 input val required, while there are 2 input for the table line!
|
||||||
|
: ... note: In instance 'top'
|
||||||
|
14 | 1 0 : 0;
|
||||||
|
| ^~~~~~~~
|
||||||
|
%Error: Exiting due to
|
16
test_regress/t/t_udp_bad_input_num.py
Executable file
16
test_regress/t/t_udp_bad_input_num.py
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 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.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('linter')
|
||||||
|
|
||||||
|
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
test.passes()
|
25
test_regress/t/t_udp_bad_input_num.v
Executable file
25
test_regress/t/t_udp_bad_input_num.v
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
primitive t_gate(dout, a, b, c);
|
||||||
|
output dout;
|
||||||
|
input a, b, c;
|
||||||
|
|
||||||
|
table
|
||||||
|
x 0 1 : 1;
|
||||||
|
0 ? 1 : 1;
|
||||||
|
1 0 : 0;
|
||||||
|
1 1 ? : 1;
|
||||||
|
1 0 0 : 0;
|
||||||
|
0 0 0 : 1;
|
||||||
|
|
||||||
|
endtable
|
||||||
|
endprimitive
|
||||||
|
module top (a, b, c, o);
|
||||||
|
input a, b, c;
|
||||||
|
output o;
|
||||||
|
t_gate(o, a, b, c);
|
||||||
|
endmodule
|
5
test_regress/t/t_udp_bad_multi_ouput.out
Normal file
5
test_regress/t/t_udp_bad_multi_ouput.out
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
%Error: t/t_udp_bad_multi_ouput.v:8:15: 2 output ports for udp table, there must be one output port!
|
||||||
|
: ... note: In instance 'top'
|
||||||
|
8 | output dout1, dout2;
|
||||||
|
| ^~~~~
|
||||||
|
%Error: Exiting due to
|
16
test_regress/t/t_udp_bad_multi_ouput.py
Executable file
16
test_regress/t/t_udp_bad_multi_ouput.py
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 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.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('linter')
|
||||||
|
|
||||||
|
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
test.passes()
|
25
test_regress/t/t_udp_bad_multi_ouput.v
Executable file
25
test_regress/t/t_udp_bad_multi_ouput.v
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
primitive t_gate(dout1, dout2, a, b, c);
|
||||||
|
output dout1, dout2;
|
||||||
|
input a, b, c;
|
||||||
|
|
||||||
|
table
|
||||||
|
x 0 1 : 1;
|
||||||
|
0 ? 1 : 1;
|
||||||
|
0 1 0 : 0;
|
||||||
|
1 1 ? : 1;
|
||||||
|
1 0 0 : 0;
|
||||||
|
0 0 0 : 1;
|
||||||
|
|
||||||
|
endtable
|
||||||
|
endprimitive
|
||||||
|
module top (a, b, c, o1, o2);
|
||||||
|
input a, b, c;
|
||||||
|
output o1, o2;
|
||||||
|
t_gate(o1, o2, a, b, c);
|
||||||
|
endmodule
|
5
test_regress/t/t_udp_sequential_bad.out
Normal file
5
test_regress/t/t_udp_sequential_bad.out
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
%Error: t/t_udp_sequential_bad.v:10:1: sequetial UDP is not suppoted currently!
|
||||||
|
: ... note: In instance 'top'
|
||||||
|
10 | reg dout;
|
||||||
|
| ^~~
|
||||||
|
%Error: Exiting due to
|
16
test_regress/t/t_udp_sequential_bad.py
Executable file
16
test_regress/t/t_udp_sequential_bad.py
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 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.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('linter')
|
||||||
|
|
||||||
|
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
test.passes()
|
26
test_regress/t/t_udp_sequential_bad.v
Executable file
26
test_regress/t/t_udp_sequential_bad.v
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
primitive or_gate(dout, a, b, c);
|
||||||
|
output dout;
|
||||||
|
input a, b, c;
|
||||||
|
reg dout;
|
||||||
|
|
||||||
|
table
|
||||||
|
x 0 1 : 1;
|
||||||
|
0 ? 1 : 1;
|
||||||
|
0 1 0 : 0;
|
||||||
|
1 1 ? : 1;
|
||||||
|
1 0 0 : 0;
|
||||||
|
0 0 0 : 1;
|
||||||
|
|
||||||
|
endtable
|
||||||
|
endprimitive
|
||||||
|
module top (a, b, c, o);
|
||||||
|
input a, b, c;
|
||||||
|
output o;
|
||||||
|
or_gate(o, a, b, c);
|
||||||
|
endmodule
|
Loading…
Reference in New Issue
Block a user