// $Id$ //-*- C++ -*- //************************************************************************* // DESCRIPTION: Verilator: Graph automata base class // // Code available from: http://www.veripool.org/verilator // // AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli // //************************************************************************* // // Copyright 2003-2008 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. // // Verilator is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // //************************************************************************* #ifndef _V3GRAPHDFA_H_ #define _V3GRAPHDFA_H_ 1 #include "config_build.h" #include "verilatedos.h" #include #include "V3Global.h" #include "V3Graph.h" class DfaGraph; class DfaVertex; class DfaEdge; //============================================================================= // NFA/DFA Graphs /// The NFA graph consists of: /// DfaVertex(START) The starting point /// DfaVertex() Interior states /// DfaVertex(ACCEPT) The completion point /// /// Transitions include a list of all inputs (arbitrary user pointers), /// 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. (If we want the complement, we /// call complement and the algorithm makes a REJECT state, then flips /// accept and reject for you.) /// /// Common transforms: /// /// "*": DfaVertex(START) --> [epsilon] -->DfaVertex(ACCEPT) /// /// "L": ...->[ON_L]-->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]-/ /// /// "L*": ...->DfaVtx-->[epsilon]-->DfaVtx-->[ON_L]-->DfaVtx()->[epsilon]-->DfaVtx(ACCEPT) /// | ^\----[epsilon]<-------/ | /// \->[epsilon]-----------------------------------------/ class DfaGraph : public V3Graph { // STATE public: DfaGraph() {} virtual ~DfaGraph() {} // METHODS /// Find start node DfaVertex* findStart(); /// Convert automata: NFA to DFA void nfaToDfa(); /// Simplify a DFA automata void dfaReduce(); /// Complement result (must already be dfa) void dfaComplement(); }; //============================================================================= // Vertex class DfaVertex : public V3GraphVertex { // Each DFA state is captured in this vertex. // Start and accepting are members, rather than the more intuitive // subclasses, as subclassing them would make it harder to inherit from here. bool m_start; // Start state bool m_accepting; // Accepting state? public: // CONSTRUCTORS DfaVertex(DfaGraph* graphp, bool start=false, bool accepting=false) : V3GraphVertex(graphp) , m_start(start), m_accepting(accepting) {} virtual DfaVertex* clone(DfaGraph* graphp) { return new DfaVertex(graphp, start(), accepting()); } virtual ~DfaVertex() {} // ACCESSORS virtual string dotShape() const { return (accepting()?"doublecircle":""); } virtual string dotColor() const { return start()?"blue":(color()?"red":"black"); } bool start() const { return m_start; } void start(bool flag) { m_start=flag; } bool accepting() const { return m_accepting; } void accepting(bool flag) { m_accepting=flag; } }; //============================================================================ /// Abstract type indicating a specific "input" to the NFA typedef AstNUser* DfaInput; //============================================================================ // Edge types 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_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" : 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; } }; //============================================================================ #endif // Guard