mirror of
https://github.com/verilator/verilator.git
synced 2025-01-11 17:17:36 +00:00
151 lines
5.8 KiB
C++
151 lines
5.8 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
//*************************************************************************
|
|
// DESCRIPTION: Verilator: Graph automata base class
|
|
//
|
|
// Code available from: https://verilator.org
|
|
//
|
|
//*************************************************************************
|
|
//
|
|
// Copyright 2003-2020 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.
|
|
//
|
|
// 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 "V3Ast.h" // for VNUser
|
|
#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 {
|
|
public:
|
|
// CONSTRUCTORS
|
|
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) {}
|
|
using V3GraphVertex::clone; // We are overriding, not overloading clone(V3Graph*)
|
|
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
|
|
/// DFA assumes each .toInt() is unique
|
|
typedef VNUser DfaInput;
|
|
|
|
//============================================================================
|
|
// Edge types
|
|
|
|
class DfaEdge : public V3GraphEdge {
|
|
DfaInput m_input;
|
|
bool m_complement; // Invert value when doing compare
|
|
public:
|
|
static DfaInput EPSILON() { return VNUser::fromInt(0); }
|
|
static DfaInput NA() { return VNUser::fromInt(1); } // as in not-applicable
|
|
// CONSTRUCTORS
|
|
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const 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(input().toInt()))
|
|
: cvtToStr(input().toInt())); }
|
|
virtual string dotStyle() const { return (na()||cutable())?"dashed":""; }
|
|
bool epsilon() const { return input().toInt()==EPSILON().toInt(); }
|
|
bool na() const { return input().toInt()==NA().toInt(); }
|
|
bool complement() const { return m_complement; }
|
|
void complement(bool value) { m_complement = value; }
|
|
DfaInput input() const { return m_input; }
|
|
};
|
|
|
|
//============================================================================
|
|
|
|
#endif // Guard
|