1 /* Copyright (C) 2015 Cotton Seed 2 3 This file is part of arachne-pnr. Arachne-pnr is free software; 4 you can redistribute it and/or modify it under the terms of the GNU 5 General Public License version 2 as published by the Free Software 6 Foundation. 7 8 This program is distributed in the hope that it will be useful, but 9 WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #ifndef PNR_NETLIST_HH 17 #define PNR_NETLIST_HH 18 19 #include "bitvector.hh" 20 #include "line_parser.hh" 21 #include "vector.hh" 22 23 #include <string> 24 #include <vector> 25 #include <set> 26 #include <map> 27 28 class Net; 29 class Port; 30 class Node; 31 class Instance; 32 class Model; 33 class Models; 34 class Design; 35 36 class Identified 37 { 38 private: 39 template<typename T> friend struct std::hash; 40 friend class IdLess; 41 42 static int id_counter; 43 int id; 44 45 public: Identified()46 Identified() 47 : id(id_counter++) 48 { 49 } 50 }; 51 52 class IdLess 53 { 54 public: operator ()(const T * lhs,const T * rhs) const55 template<typename T> bool operator()(const T *lhs, const T *rhs) const 56 { 57 return static_cast<const Identified*>(lhs)->id < static_cast<const Identified*>(rhs)->id; 58 } 59 }; 60 61 namespace std { 62 63 template<> 64 struct hash<Identified *> 65 { 66 public: operator ()std::hash67 size_t operator()(const Identified *x) const 68 { 69 std::hash<int> hasher; 70 return hasher(x->id); 71 } 72 }; 73 74 template<> struct hash<Net *> : public std::hash<Identified *> {}; 75 template<> struct hash<Node *> : public std::hash<Identified *> {}; 76 template<> struct hash<Instance *> : public std::hash<Identified *> {}; 77 template<> struct hash<Model *> : public std::hash<Identified *> {}; 78 79 } 80 81 enum class Direction 82 { 83 IN, OUT, INOUT, 84 }; 85 86 Direction opposite_direction(Direction d); 87 88 enum class Value 89 { 90 ZERO, ONE, X, Z, 91 }; 92 93 // for parameters, attributes 94 class Const 95 { 96 private: 97 friend std::ostream &operator<<(std::ostream &s, const Const &c); 98 99 LexicalPosition m_lp; 100 bool m_is_bits; 101 std::string m_strval; 102 BitVector m_bitval; 103 104 public: lexpos() const105 const LexicalPosition &lexpos() const { return m_lp; } 106 107 public: Const()108 Const() : m_is_bits(false) {} Const(const std::string & sv)109 Const(const std::string &sv) 110 : m_is_bits(false), m_strval(sv) 111 {} Const(const LexicalPosition & lp,const std::string & sv)112 Const(const LexicalPosition &lp, const std::string &sv) 113 : m_lp(lp), m_is_bits(false), m_strval(sv) 114 {} Const(const BitVector & bv)115 Const(const BitVector &bv) 116 : m_is_bits(true), m_bitval(bv) 117 {} Const(const LexicalPosition & lp,const BitVector & bv)118 Const(const LexicalPosition &lp, const BitVector &bv) 119 : m_lp(lp), m_is_bits(true), m_bitval(bv) 120 {} 121 as_string() const122 const std::string &as_string() const 123 { 124 if (m_is_bits) 125 m_lp.fatal("expected string constant"); 126 return m_strval; 127 } 128 as_bits() const129 const BitVector &as_bits() const 130 { 131 if (!m_is_bits) 132 m_lp.fatal("expected integer constant"); 133 return m_bitval; 134 } 135 get_bit(int i) const136 bool get_bit(int i) const 137 { 138 if (!m_is_bits) 139 m_lp.fatal("expected integer constant"); 140 if (i >= (int)m_bitval.size()) 141 return 0; 142 else 143 return m_bitval[i]; 144 } 145 146 void write_verilog(std::ostream &s) const; 147 }; 148 149 150 class Net : public Identified 151 { 152 friend class Port; 153 friend class Model; 154 155 std::string m_name; 156 bool m_is_constant; 157 Value m_constant; 158 159 std::set<Port *, IdLess> m_connections; 160 161 public: name() const162 const std::string &name() const { return m_name; } 163 is_constant() const164 bool is_constant() const { return m_is_constant; } set_is_constant(bool c)165 void set_is_constant(bool c) { m_is_constant = c; } constant() const166 Value constant() const { return m_constant; } set_constant(Value c)167 void set_constant(Value c) { m_constant = c; } 168 connections() const169 const std::set<Port *, IdLess> &connections() const { return m_connections; } 170 Net(const std::string & n)171 Net(const std::string &n) 172 : m_name(n), m_is_constant(false), m_constant(Value::X) 173 { 174 } 175 ~Net()176 ~Net() 177 { 178 assert(m_connections.empty()); 179 } 180 181 void replace(Net *new_n); 182 }; 183 184 class Port : public Identified 185 { 186 Node *m_node; 187 std::string m_name; 188 Direction m_dir; 189 Value m_undriven; 190 Net *m_connection; 191 192 public: node() const193 Node *node() const { return m_node; } name() const194 const std::string &name() const { return m_name; } direction() const195 Direction direction() const { return m_dir; } set_direction(Direction dir)196 void set_direction(Direction dir) { m_dir = dir; } undriven() const197 Value undriven() const { return m_undriven; } set_undriven(Value u)198 void set_undriven(Value u) { m_undriven = u; } 199 Port(Node * node_,const std::string & name_)200 Port(Node *node_, const std::string &name_) 201 : m_node(node_), m_name(name_), m_dir(Direction::IN), m_undriven(Value::X), m_connection(nullptr) 202 {} Port(Node * node_,const std::string & name_,Direction dir)203 Port(Node *node_, const std::string &name_, Direction dir) 204 : m_node(node_), m_name(name_), m_dir(dir), m_undriven(Value::X), m_connection(nullptr) 205 {} Port(Node * node_,const std::string & name_,Direction dir,Value u)206 Port(Node *node_, const std::string &name_, Direction dir, Value u) 207 : m_node(node_), m_name(name_), m_dir(dir), m_undriven(u), m_connection(nullptr) 208 {} ~Port()209 ~Port() 210 { 211 assert(m_connection == nullptr); 212 } 213 214 /* from the perspective of the body of a model */ 215 bool is_output() const; 216 bool is_input() const; is_bidir() const217 bool is_bidir() const { return m_dir == Direction::INOUT; } 218 connected() const219 bool connected() const { return m_connection != nullptr; } 220 void disconnect(); 221 void connect(Net *n); connection() const222 Net *connection() const { return m_connection; } 223 224 Port *connection_other_port() const; 225 }; 226 227 class Node : public Identified 228 { 229 protected: 230 std::map<std::string, Port *> m_ports; 231 std::vector<Port *> m_ordered_ports; 232 233 public: 234 typedef Node Base; 235 enum class Kind 236 { 237 model, 238 instance, 239 }; 240 private: 241 Kind m_kind; 242 243 public: ports() const244 const std::map<std::string, Port *> &ports() const { return m_ports; } ordered_ports() const245 const std::vector<Port *> &ordered_ports() const { return m_ordered_ports; } 246 kind() const247 Kind kind() const { return m_kind; } 248 Node(Kind k)249 Node(Kind k) : m_kind(k) {} 250 ~Node(); 251 252 Port *add_port(Port *t); 253 Port *add_port(const std::string &n, Direction dir); 254 Port *add_port(const std::string &n, Direction dir, Value u); 255 Port *find_port(const std::string &n); 256 }; 257 258 class Instance : public Node 259 { 260 Model *m_parent; 261 Model *m_instance_of; 262 263 std::map<std::string, Const> m_params; 264 std::map<std::string, Const> m_attrs; 265 266 public: 267 static const Kind kindof = Kind::instance; 268 parent() const269 Model *parent() const { return m_parent; } instance_of() const270 Model *instance_of() const { return m_instance_of; } attrs() const271 const std::map<std::string, Const> &attrs() const { return m_attrs; } params() const272 const std::map<std::string, Const> ¶ms() const { return m_params; } 273 274 Instance(Model *p, Model *inst_of); 275 set_attr(const std::string & an,const Const & val)276 void set_attr(const std::string &an, const Const &val) { m_attrs[an] = val; } 277 has_attr(const std::string & an) const278 bool has_attr(const std::string &an) const 279 { 280 return contains_key(m_attrs, an); 281 } 282 get_attr(const std::string & an) const283 const Const &get_attr(const std::string &an) const 284 { 285 return m_attrs.at(an); 286 } 287 // Return true if an attr exists and is set to 1, defval otherwise 288 // (for binary attributes like ROUTE_THROUGH_FABRIC) is_attr_set(const std::string & an,bool defval=false) const289 bool is_attr_set(const std::string &an, bool defval = false) const 290 { 291 if(!has_attr(an)) 292 return defval; 293 else 294 return get_attr(an).get_bit(0); 295 } 296 297 void merge_attrs(const Instance *inst); 298 set_param(const std::string & pn,const Const & val)299 void set_param(const std::string &pn, const Const &val) { m_params[pn] = val; } 300 301 bool has_param(const std::string &pn) const; 302 const Const &get_param(const std::string &pn) const; 303 self_has_param(const std::string & pn) const304 bool self_has_param(const std::string &pn) const { return contains_key(m_params, pn); } 305 const Const & self_get_param(const std::string & pn) const306 self_get_param(const std::string &pn) const 307 { 308 return m_params.at(pn); 309 } 310 311 void remove(); 312 313 void dump() const; 314 void write_blif(std::ostream &s, 315 const std::map<Net *, std::string, IdLess> &net_name) const; 316 void write_verilog(std::ostream &s, 317 const std::map<Net *, std::string, IdLess> &net_name, 318 const std::string &inst_name) const; 319 }; 320 321 class Model : public Node 322 { 323 friend class Instance; 324 325 static int counter; 326 327 std::string m_name; 328 std::map<std::string, Net *> m_nets; 329 std::set<Instance *, IdLess> m_instances; 330 331 std::map<std::string, Const> m_params; 332 333 public: 334 static const Kind kindof = Kind::model; 335 name() const336 const std::string &name() const { return m_name; } 337 instances() const338 const std::set<Instance *, IdLess> &instances() const { return m_instances; } nets() const339 const std::map<std::string, Net *> &nets() const { return m_nets; } params() const340 const std::map<std::string, Const> ¶ms() const { return m_params; } 341 342 Model(Design *d, const std::string &n); 343 ~Model(); 344 345 Net *find_net(const std::string &n); 346 Net *find_or_add_net(const std::string &n); 347 Net *add_net(); 348 Net *add_net(const std::string &name); add_net(Net * orig)349 Net *add_net(Net *orig) { return add_net(orig->name()); } 350 void remove_net(Net *n); 351 Instance *add_instance(Model *inst_of); 352 353 void set_param(const std::string & pn,const std::string & val)354 set_param(const std::string &pn, const std::string &val) 355 { 356 m_params[pn] = Const(val); 357 } 358 359 void set_param(const std::string & pn,const BitVector & val)360 set_param(const std::string &pn, const BitVector &val) 361 { 362 m_params[pn] = Const(val); 363 } 364 365 const Const & get_param(const std::string & pn)366 get_param(const std::string &pn) 367 { 368 return m_params.at(pn); 369 } 370 has_param(const std::string & pn)371 bool has_param(const std::string &pn) { return contains_key(m_params, pn); } 372 373 bool is_physical_port(Models &models, const Port *p) const; 374 void check_boundary_nets(const Design *d) const; 375 std::set<Net *, IdLess> boundary_nets(const Design *d) const; 376 std::pair<std::vector<Net *>, std::map<Net *, int, IdLess>> 377 index_nets() const; 378 std::pair<std::vector<Net *>, std::map<Net *, int, IdLess>> 379 index_internal_nets(const Design *d) const; 380 381 std::pair<BasedVector<Instance *, 1>, std::map<Instance *, int, IdLess>> 382 index_instances() const; 383 384 void prune(); 385 386 std::pair<std::map<Net *, std::string, IdLess>, 387 std::set<Net *, IdLess>> 388 shared_names() const; 389 void write_verilog(std::ostream &s) const; 390 void write_blif(std::ostream &s) const; 391 void rename_net(Net *n, const std::string &new_name); 392 #ifndef NDEBUG 393 void check(const Design *d) const; 394 #endif 395 }; 396 397 class Design 398 { 399 friend class Model; 400 401 Model *m_top; 402 std::map<std::string, Model *> m_models; 403 404 public: top() const405 Model *top() const { return m_top; } 406 void set_top(Model *t); 407 408 Design(); 409 ~Design(); 410 411 void create_standard_models(); 412 Model *find_model(const std::string &n) const; 413 void prune(); 414 void write_verilog(std::ostream &s) const; 415 void write_blif(std::ostream &s) const; 416 void dump() const; 417 void check_boundary_nets() const; 418 #ifndef NDEBUG 419 void check() const; 420 #endif 421 }; 422 423 class Models 424 { 425 public: 426 Model *lut4, 427 *carry; 428 Model *lc, 429 *io, 430 *gb, 431 *gb_io, 432 *ram, 433 *ramnr, 434 *ramnw, 435 *ramnrnw, 436 *warmboot, 437 *tbuf, 438 *io_i3c, 439 *io_od; 440 441 public: 442 Models(const Design *d); 443 is_dff(Instance * inst) const444 bool is_dff(Instance *inst) const 445 { 446 return is_prefix("SB_DFF", inst->instance_of()->name()); 447 } is_lut4(Instance * inst) const448 bool is_lut4(Instance *inst) const { return inst->instance_of() == lut4; } is_carry(Instance * inst) const449 bool is_carry(Instance *inst) const { return inst->instance_of() == carry; } 450 is_lc(Instance * inst) const451 bool is_lc(Instance *inst) const { return inst->instance_of() == lc; } is_io(Instance * inst) const452 bool is_io(Instance *inst) const { return inst->instance_of() == io; } is_gb(Instance * inst) const453 bool is_gb(Instance *inst) const { return inst->instance_of() == gb; } is_gb_io(const Instance * inst) const454 bool is_gb_io(const Instance *inst) const { return inst->instance_of() == gb_io; } is_io_i3c(const Instance * inst) const455 bool is_io_i3c(const Instance *inst) const { return inst->instance_of() == io_i3c; } is_io_od(const Instance * inst) const456 bool is_io_od(const Instance *inst) const { return inst->instance_of() == io_od; } 457 is_ioX(const Instance * inst) const458 bool is_ioX(const Instance *inst) const 459 { 460 return inst->instance_of() == io 461 || inst->instance_of() == gb_io 462 || inst->instance_of() == io_i3c 463 || inst->instance_of() == io_od; 464 465 } is_gbX(const Instance * inst) const466 bool is_gbX(const Instance *inst) const 467 { 468 return inst->instance_of() == gb 469 || inst->instance_of() == gb_io; 470 } 471 is_ram(Instance * inst) const472 bool is_ram(Instance *inst) const { return inst->instance_of() == ram; } is_ramnr(Instance * inst) const473 bool is_ramnr(Instance *inst) const { return inst->instance_of() == ramnr; } is_ramnw(Instance * inst) const474 bool is_ramnw(Instance *inst) const { return inst->instance_of() == ramnw; } is_ramnrnw(Instance * inst) const475 bool is_ramnrnw(Instance *inst) const { return inst->instance_of() == ramnrnw; } is_warmboot(Instance * inst) const476 bool is_warmboot(Instance *inst) const { return inst->instance_of() == warmboot; } is_tbuf(Instance * inst) const477 bool is_tbuf(Instance *inst) const { return inst->instance_of() == tbuf; } 478 is_ramX(Instance * inst) const479 bool is_ramX(Instance *inst) const 480 { 481 return (inst->instance_of() == ram 482 || inst->instance_of() == ramnr 483 || inst->instance_of() == ramnw 484 || inst->instance_of() == ramnrnw); 485 } is_pllX(const Instance * inst) const486 bool is_pllX(const Instance *inst) const 487 { 488 return is_prefix("SB_PLL40_", inst->instance_of()->name()); 489 } is_mac16(const Instance * inst) const490 bool is_mac16(const Instance *inst) const {return inst->instance_of()->name() == "SB_MAC16";} is_spram(const Instance * inst) const491 bool is_spram(const Instance *inst) const {return inst->instance_of()->name() == "SB_SPRAM256KA";} is_hfosc(const Instance * inst) const492 bool is_hfosc(const Instance *inst) const {return inst->instance_of()->name() == "SB_HFOSC" || inst->instance_of()->name() == "SB_HFOSC_TRIM";} is_hfosc_trim(const Instance * inst) const493 bool is_hfosc_trim(const Instance *inst) const {return inst->instance_of()->name() == "SB_HFOSC_TRIM";} 494 is_lfosc(const Instance * inst) const495 bool is_lfosc(const Instance *inst) const {return inst->instance_of()->name() == "SB_LFOSC";} is_rgba_drv(const Instance * inst) const496 bool is_rgba_drv(const Instance *inst) const {return inst->instance_of()->name() == "SB_RGBA_DRV";} is_ledda_ip(const Instance * inst) const497 bool is_ledda_ip(const Instance *inst) const {return inst->instance_of()->name() == "SB_LEDDA_IP";} is_i2c(const Instance * inst) const498 bool is_i2c(const Instance *inst) const {return inst->instance_of()->name() == "SB_I2C";} is_spi(const Instance * inst) const499 bool is_spi(const Instance *inst) const {return inst->instance_of()->name() == "SB_SPI";} 500 501 }; 502 503 504 #endif 505