diff --git a/design_dump.cc b/design_dump.cc index 5a97b5ec0..d7eb4027b 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -688,6 +688,14 @@ void NetFF::dump_node(ostream&o, unsigned ind) const dump_obj_attr(o, ind+4); } +void NetLatch::dump_node(ostream&o, unsigned ind) const +{ + o << setw(ind) << "" << "LPM_LATCH: " << name() + << " scope=" << scope_path(scope()) << endl; + dump_node_pins(o, ind+4); + dump_obj_attr(o, ind+4); +} + void NetLiteral::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "constant real " << real_ diff --git a/emit.cc b/emit.cc index bd46fc5c4..adc582293 100644 --- a/emit.cc +++ b/emit.cc @@ -123,6 +123,12 @@ bool NetFF::emit_node(struct target_t*tgt) const return true; } +bool NetLatch::emit_node(struct target_t*tgt) const +{ + tgt->lpm_latch(this); + return true; +} + bool NetLiteral::emit_node(struct target_t*tgt) const { return tgt->net_literal(this); diff --git a/functor.cc b/functor.cc index 75ed5a606..280a6f9aa 100644 --- a/functor.cc +++ b/functor.cc @@ -78,6 +78,10 @@ void functor_t::lpm_ff(Design*, NetFF*) { } +void functor_t::lpm_latch(Design*, NetLatch*) +{ +} + void functor_t::lpm_logic(Design*, NetLogic*) { } @@ -219,6 +223,11 @@ void NetFF::functor_node(Design*des, functor_t*fun) fun->lpm_ff(des, this); } +void NetLatch::functor_node(Design*des, functor_t*fun) +{ + fun->lpm_latch(des, this); +} + void NetLiteral::functor_node(Design*des, functor_t*fun) { fun->lpm_literal(des, this); diff --git a/functor.h b/functor.h index 63d85a755..716ceda64 100644 --- a/functor.h +++ b/functor.h @@ -75,6 +75,9 @@ struct functor_t { /* This method is called for each FF in the design. */ virtual void lpm_ff(class Design*des, class NetFF*); + /* This method is called for each LATCH in the design. */ + virtual void lpm_latch(class Design*des, class NetLatch*); + /* Handle LPM combinational logic devices. */ virtual void lpm_logic(class Design*des, class NetLogic*); diff --git a/netlist.cc b/netlist.cc index 211083a17..34b3ebf28 100644 --- a/netlist.cc +++ b/netlist.cc @@ -1306,6 +1306,60 @@ const verinum& NetFF::sset_value() const return sset_value_; } +/* + * The NetLatch class represents an LPM_LATCH device. The pinout is assigned + * like so: + * 0 -- Enable + * 1 -- Data + * 2 -- Q + */ + +NetLatch::NetLatch(NetScope*s, perm_string n, unsigned width__) +: NetNode(s, n, 3), width_(width__) +{ + pin_Enable().set_dir(Link::INPUT); + pin_Data().set_dir(Link::INPUT); + pin_Q().set_dir(Link::OUTPUT); +} + +NetLatch::~NetLatch() +{ +} + +unsigned NetLatch::width() const +{ + return width_; +} + +Link& NetLatch::pin_Enable() +{ + return pin(0); +} + +const Link& NetLatch::pin_Enable() const +{ + return pin(0); +} + +Link& NetLatch::pin_Data() +{ + return pin(1); +} + +const Link& NetLatch::pin_Data() const +{ + return pin(1); +} + +Link& NetLatch::pin_Q() +{ + return pin(2); +} + +const Link& NetLatch::pin_Q() const +{ + return pin(2); +} NetAbs::NetAbs(NetScope*s, perm_string n, unsigned w) : NetNode(s, n, 2), width_(w) diff --git a/netlist.h b/netlist.h index d6fe7358a..710aa4b82 100644 --- a/netlist.h +++ b/netlist.h @@ -1684,6 +1684,35 @@ class NetFF : public NetNode { verinum sset_value_; }; + +/* + * This class represents an LPM_LATCH device. There is no literal gate + * type in Verilog that maps, but gates of this type can be inferred. + */ +class NetLatch : public NetNode { + + public: + NetLatch(NetScope*s, perm_string n, unsigned vector_width); + ~NetLatch(); + + unsigned width() const; + + Link& pin_Enable(); + Link& pin_Data(); + Link& pin_Q(); + + const Link& pin_Enable() const; + const Link& pin_Data() const; + const Link& pin_Q() const; + + virtual void dump_node(ostream&, unsigned ind) const; + virtual bool emit_node(struct target_t*) const; + virtual void functor_node(Design*des, functor_t*fun); + + private: + unsigned width_; +}; + /* * This class implements a basic LPM_MULT combinational multiplier. It * is used as a structural representation of the * operator. The diff --git a/target.cc b/target.cc index a4fe8b44a..b268e5192 100644 --- a/target.cc +++ b/target.cc @@ -183,6 +183,12 @@ void target_t::lpm_ff(const NetFF*) "Unhandled NetFF." << endl; } +void target_t::lpm_latch(const NetLatch*) +{ + cerr << "target (" << typeid(*this).name() << "): " + "Unhandled NetLatch." << endl; +} + void target_t::lpm_mult(const NetMult*) { cerr << "target (" << typeid(*this).name() << "): " diff --git a/target.h b/target.h index ec834418d..39ddd7b8f 100644 --- a/target.h +++ b/target.h @@ -98,6 +98,7 @@ struct target_t { virtual void lpm_mult(const NetMult*); virtual void lpm_mux(const NetMux*); virtual void lpm_pow(const NetPow*); + virtual void lpm_latch(const NetLatch*); virtual bool concat(const NetConcat*); virtual bool part_select(const NetPartSelect*);