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> &params() 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> &params() 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