Add graph dfa complementing; not used yet.

git-svn-id: file://localhost/svn/verilator/trunk/verilator@1005 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2008-03-23 13:56:06 +00:00
parent ede37bb9d8
commit 6dca9b4ba4
3 changed files with 124 additions and 6 deletions

View File

@ -480,3 +480,97 @@ public:
void DfaGraph::dfaReduce() {
DfaGraphReduce (this, &V3GraphEdge::followAlwaysTrue);
}
//######################################################################
//######################################################################
// Algorithms - complement a DFA
//
// The traditional algorithm is to make a rejecting state, add edges to
// reject from all missing values, then swap accept and reject. Rather
// than swap at the end, it's faster if we swap up front, then do the edge
// changes.
//
// 1. Since we didn't log rejecting states, make a temp state (this will be
// the old accept, and new reject).
//
// 2. All vertexes except start/accept get edges to NEW accept for any
// non-existing case. Weedely we don't have a nice way of representing
// this so we just create a edge for each case and mark it "complemented."
//
// 3. Delete temp vertex (old accept/new reject) and related edges.
// The user's old accept is now the new accept. This is imporant as
// we want the virtual type of it to be intact.
class DfaGraphComplement : GraphAlg {
private:
// MEMBERS
DfaVertex* m_tempNewerReject;
// METHODS
int debug() { return 9; }
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
void add_complement_edges() {
// Find accepting vertex
DfaVertex* acceptp = NULL;
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
if (vvertexp->accepting()) {
acceptp = vvertexp;
break;
}
}
}
if (!acceptp) v3fatalSrc("No accepting vertex in DFA\n");
// Remap edges
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
//UINFO(0, "FIX on vertex "<<vvertexp->name()<<endl);
if (!vvertexp->accepting() && vvertexp != m_tempNewerReject) {
for (V3GraphEdge* nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
nextp = edgep->outNextp();
if (!edgep->user()) { // Not processed
// Old edges to accept now go to new reject
DfaEdge* vedgep = static_cast<DfaEdge*>(edgep);
DfaVertex* tovertexp = static_cast<DfaVertex*>(edgep->top());
if (tovertexp->accepting()) {
new DfaEdge(graphp(), vvertexp, m_tempNewerReject, vedgep);
edgep->unlinkDelete(); edgep=NULL;
}
// NOT of all values goes to accept
// We make a edge for each value to OR, IE
// edge(complemented,a) edge(complemented,b) means !(a | b)
if (!tovertexp->accepting()) { // Note we must include edges moved above to reject
DfaEdge* newp = new DfaEdge (graphp(), vvertexp, acceptp, vedgep);
newp->complement(!newp->complement());
newp->user(1);
}
}
}
}
}
}
}
public:
DfaGraphComplement(V3Graph* dfagraphp, V3EdgeFuncP edgeFuncp)
: GraphAlg(dfagraphp, edgeFuncp) {
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_in");
// Vertex::m_user begin: 1 indicates new edge, no more processing
m_graphp->userClearEdges();
m_tempNewerReject = new DfaVertex(graphp());
add_complement_edges();
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_preswap");
m_tempNewerReject->unlinkDelete(graphp()); m_tempNewerReject=NULL;
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_out");
}
~DfaGraphComplement() {}
};
void DfaGraph::dfaComplement() {
DfaGraphComplement (this, &V3GraphEdge::followAlwaysTrue);
}

View File

@ -43,7 +43,9 @@ class DfaEdge;
/// or epsilon, represented as a empty list of inputs.
///
/// We're only looking for matches, so the only accepting states are
/// at the end of the transformations.
/// at the end of the transformations. (If we want the complement, we
/// call complement and the algorithm makes a REJECT state, then flips
/// accept and reject for you.)
///
/// Common transforms:
///
@ -51,8 +53,8 @@ class DfaEdge;
///
/// "L": ...->[ON_L]-->DfaVtx-->[epsilon]-->DfaVtx(ACCEPT)
///
/// "LR": ...->[ON_L]-->DfaVtx-->[epsilon]-->DfaVtx()
/// ->[ON_R]-->DfaVtx-->[epsilon]-->DfaVtx(ACCEPT)
/// "LR": ...->[ON_L]-->DfaVtx-->[epsilon]-->DfaVtx(ACCEPT)
/// ->[ON_R]-->DfaVtx-->[epsilon]-/
///
/// "L|R": ...->DfaVtx-->[epsilon]-->DfaVtx-->[ON_L]-->DfaVtx()->[epsilon]-->DfaVtx(ACCEPT)
/// \->[epsilon]-->DfaVtx-->[ON_R]-->DfaVtx()->[epsilon]-/
@ -76,6 +78,9 @@ public:
/// Simplify a DFA automata
void dfaReduce();
/// Complement result (must already be dfa)
void dfaComplement();
};
//=============================================================================
@ -113,20 +118,33 @@ typedef AstNUser* DfaInput;
class DfaEdge : public V3GraphEdge {
DfaInput m_input;
bool m_complement; // Invert value when doing compare
public:
static DfaInput EPSILON() { return NULL; }
static DfaInput NA() { return AstNUser::fromInt(1); } // as in not-applicable
// CONSTRUCTORS
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, DfaInput input)
: V3GraphEdge(graphp, fromp, top, 1)
, m_input(input) {}
, m_input(input), m_complement(false) {}
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaEdge* copyfrom)
: V3GraphEdge(graphp, fromp, top, copyfrom->weight())
, m_input(copyfrom->input()), m_complement(copyfrom->complement()) {}
virtual ~DfaEdge() {}
// METHODS
virtual string dotColor() const { return na()?"yellow":epsilon()?"green":"black"; }
virtual string dotLabel() const { return na()?"":epsilon()?"e":cvtToStr((void*)(input())); }
virtual string dotColor() const {
return (na() ? "yellow"
: epsilon() ? "green"
: "black"); }
virtual string dotLabel() const {
return (na() ? ""
: epsilon() ? "e"
: complement() ? ("not "+cvtToStr((void*)(input())))
: cvtToStr((void*)(input()))); }
virtual string dotStyle() const { return (na()||cutable())?"dashed":""; }
bool epsilon() const { return input()==EPSILON(); }
bool na() const { return input()==NA(); }
bool complement() const { return m_complement; }
void complement(bool value) { m_complement=value; }
DfaInput input() const { return m_input; }
};

View File

@ -309,6 +309,12 @@ public:
gp->nfaToDfa();
dump();
gp->dfaReduce();
dump();
gp->dfaComplement();
dump();
gp->dfaReduce();
dump();
}
};