Sdf.hh 6.39 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2019, Parallax Software, Inc.
// 
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program 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.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#ifndef STA_SDF_H
#define STA_SDF_H

#include "DisallowCopyAssign.hh"
#include "Zlib.hh"
#include "Vector.hh"
#include "TimingRole.hh"
#include "Transition.hh"
#include "LibertyClass.hh"
#include "NetworkClass.hh"
#include "GraphClass.hh"
#include "SdcClass.hh"
#include "StaState.hh"

// Header for ReadSdf.cc to communicate with SdfLex.cc, SdfParse.cc

// global namespace

#define YY_INPUT(buf,result,max_size) \
  sta::sdf_reader->getChars(buf, result, max_size)
int
SdfParse_error(const char *msg);

namespace sta {

class Report;
class SdfTriple;
class SdfPortSpec;

typedef Vector<SdfTriple*> SdfTripleSeq;

class SdfReader : public StaState
{
public:
  SdfReader(const char *filename,
	    const char *path,
	    int arc_min_index,
	    int triple_min_index,
	    int arc_max_index,
	    int triple_max_index,
	    AnalysisType analysis_type,
	    bool unescaped_dividers,
	    bool is_incremental_only,
            MinMaxAll *cond_use,
	    StaState *sta);
  ~SdfReader();
  bool read();
  // Arc/Triple index passed to read() to ignore arg.
  static int nullIndex() { return null_index_; }

  void setDivider(char divider);
  void setTimescale(float multiplier, const char *units);
  void setPortDeviceDelay(Edge *edge,
			  SdfTripleSeq *triples,
			  bool from_trans);
  void setEdgeArcDelays(Edge *edge,
			TimingArc *arc,
			SdfTriple *triple);
  void setEdgeArcDelays(Edge *edge,
			TimingArc *arc,
			SdfTriple *triple,
			int triple_index,
			int arc_delay_index);
  void setEdgeArcDelaysCondUse(Edge *edge,
			       TimingArc *arc,
			       SdfTriple *triple);
  void setEdgeArcDelaysCondUse(Edge *edge,
			       TimingArc *arc,
			       float *value,
			       int triple_index,
			       int arc_delay_index,
			       const MinMax *min_max);
  void setInstance(const char *instance_name);
  void setInstanceWildcard();
  void cellFinish();
  void setCell(const char *cell_name);
  void interconnect(const char *from_pin_name,
		    const char *to_pin_name,
		    SdfTripleSeq *triples);
  void iopath(SdfPortSpec *from_edge,
	      const char *to_port_name,
	      SdfTripleSeq *triples,
	      const char *cond,
	      bool condelse);
  void timingCheck(TimingRole *role,
		   SdfPortSpec *data_edge,
		   SdfPortSpec *clk_edge,
		   SdfTriple *triple);
  void timingCheckWidth(SdfPortSpec *edge,
			SdfTriple *triple);
  void timingCheckPeriod(SdfPortSpec *edge,
			 SdfTriple *triple);
  void timingCheckSetupHold(SdfPortSpec *data_edge,
			    SdfPortSpec *clk_edge,
			    SdfTriple *setup_triple,
			    SdfTriple *hold_triple);
  void timingCheckRecRem(SdfPortSpec *data_edge,
			 SdfPortSpec *clk_edge,
			 SdfTriple *rec_triple,
			 SdfTriple *rem_triple);
  void timingCheckNochange(SdfPortSpec *data_edge,
			   SdfPortSpec *clk_edge,
			   SdfTriple *before_triple,
			   SdfTriple *after_triple);
  void port(const char *to_pin_name,
	    SdfTripleSeq *triples);
  void device(SdfTripleSeq *triples);
  void device(const char *to_pin_name,
	      SdfTripleSeq *triples);

  SdfTriple *makeTriple();
  SdfTriple *makeTriple(float value);
  SdfTriple *makeTriple(float *min,
			float *typ,
			float *max);
  void deleteTriple(SdfTriple *triple);
  SdfTripleSeq *makeTripleSeq();
  void deleteTripleSeq(SdfTripleSeq *triples);
  SdfPortSpec *makePortSpec(Transition *tr,
			    const char *port,
			    const char *cond);
  SdfPortSpec *makeCondPortSpec(char *cond_port);
  const char *unescaped(const char *s);
  // Parser state used to control lexer for COND handling.
  bool inTimingCheck() { return in_timing_check_; }
  void setInTimingCheck(bool in);
  bool inIncremental() const { return in_incremental_; }
  void setInIncremental(bool incr);

  // flex YY_INPUT yy_n_chars arg changed definition from int to size_t,
  // so provide both forms.
  void getChars(char *buf,
		size_t &result,
		size_t max_size);
  void getChars(char *buf,
		int &result,
		size_t max_size);
  void incrLine();
  const char *filename() { return filename_; }
  int line() { return line_; }
  void sdfError(const char *fmt, ...);
  void notSupported(const char *feature);

private:
  DISALLOW_COPY_AND_ASSIGN(SdfReader);
  int readSdfFile1(Network *network,
		   Graph *graph,
		   const char *filename);
  Edge *findCheckEdge(Pin *from_pin,
		      Pin *to_pin,
		      TimingRole *sdf_role,
		      const char *cond_start,
		      const char *cond_end);
  Edge *findWireEdge(Pin *from_pin,
		     Pin *to_pin);
  bool condMatch(const char *sdf_cond,
		 const char *lib_cond);
  void timingCheck1(TimingRole *role,
		    SdfPortSpec *data_edge,
		    SdfPortSpec *clk_edge,
		    SdfTriple *triple,
		    bool warn);
  bool annotateCheckEdges(Pin *data_pin,
			  SdfPortSpec *data_edge,
			  Pin *clk_pin,
			  SdfPortSpec *clk_edge,
			  TimingRole *sdf_role,
			  SdfTriple *triple,
			  bool match_generic);
  void deletePortSpec(SdfPortSpec *edge);
  void portNotFound(const char *port_name);
  Pin *findPin(const char *name);
  Instance *findInstance(const char *name);
  void setEdgeDelays(Edge *edge,
		     SdfTripleSeq *triples,
		     const char *sdf_cmd);
  void setDevicePinDelays(Pin *to_pin,
			  SdfTripleSeq *triples);

  const char *filename_;
  const char *path_;
  // Which values to pull out of the sdf triples.
  int triple_min_index_;
  int triple_max_index_;
  // Which arc delay value to deposit the sdf values into.
  int arc_delay_min_index_;
  int arc_delay_max_index_;
  AnalysisType analysis_type_;
  bool unescaped_dividers_;
  bool is_incremental_only_;
  MinMaxAll *cond_use_;

  int line_;
  gzFile stream_;
  char divider_;
  char escape_;
  Instance *instance_;
  const char *cell_name_;
  bool in_timing_check_;
  bool in_incremental_;
  float timescale_;

  static const int null_index_ = -1;
};

extern SdfReader *sdf_reader;

} // namespace
#endif