diff --git a/Makefile.in b/Makefile.in index 6e4c96ab3..04422581b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -106,7 +106,7 @@ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ load_module.o netlist.o netmisc.o net_assign.o \ net_design.o net_event.o net_expr.o net_force.o net_func.o \ net_link.o net_modulo.o net_nex_input.o net_nex_output.o \ -net_proc.o net_scope.o net_udp.o pad_to_width.o \ +net_proc.o net_scope.o net_tran.o net_udp.o pad_to_width.o \ parse.o parse_misc.o pform.o pform_disciplines.o pform_dump.o pform_types.o \ set_width.o symbol_search.o sync.o sys_funcs.o \ verinum.o verireal.o target.o targets.o \ diff --git a/design_dump.cc b/design_dump.cc index 3c00083a8..1d408ffd8 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -611,6 +611,17 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const o << setw(ind) << "" << "endtask" << endl; } +void NetTran::dump_node(ostream&o, unsigned ind) const +{ + const char*r = resistive_? "r" : ""; + const char*ifx = enable_==0? "" : enable_>0? "if1" : "if0"; + + o << setw(ind) << "" << r << "tran" << ifx << " " << name() << endl; + + dump_node_pins(o, ind+4); + dump_obj_attr(o, ind+4); +} + void NetUDP::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "UDP (" << udp_name() << "): "; diff --git a/elaborate.cc b/elaborate.cc index abc12b2ca..d4ca9b9df 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -419,7 +419,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const } /* Allocate all the netlist nodes for the gates. */ - NetLogic**cur = new NetLogic*[count]; + NetNode**cur = new NetNode*[count]; assert(cur); /* Calculate the gate delays from the delay expressions @@ -659,6 +659,67 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const cur[idx] = new NetLogic(scope, inm, pin_count(), NetLogic::XOR, instance_width); break; + case TRAN: + if (pin_count() != 2) { + cerr << get_fileline() << ": error: Pin count for " + << "tran device." << endl; + des->errors += 1; + return; + } else { + cur[idx] = new NetTran(scope, inm, false, 0); + } + break; + case RTRAN: + if (pin_count() != 2) { + cerr << get_fileline() << ": error: Pin count for " + << "rtran device." << endl; + des->errors += 1; + return; + } else { + cur[idx] = new NetTran(scope, inm, true, 0); + return; + } + break; + case TRANIF0: + if (pin_count() != 3) { + cerr << get_fileline() << ": error: Pin count for " + << "tranif0 device." << endl; + des->errors += 1; + return; + } else { + cur[idx] = new NetTran(scope, inm, false, -1); + } + break; + case RTRANIF0: + if (pin_count() != 3) { + cerr << get_fileline() << ": error: Pin count for " + << "rtranif0 device." << endl; + des->errors += 1; + return; + } else { + cur[idx] = new NetTran(scope, inm, true, -1); + } + break; + case TRANIF1: + if (pin_count() != 3) { + cerr << get_fileline() << ": error: Pin count for " + << "tranif1 device." << endl; + des->errors += 1; + return; + } else { + cur[idx] = new NetTran(scope, inm, false, 1); + } + break; + case RTRANIF1: + if (pin_count() != 3) { + cerr << get_fileline() << ": error: Pin count for " + << "rtranif1 device." << endl; + des->errors += 1; + return; + } else { + cur[idx] = new NetTran(scope, inm, true, 1); + } + break; default: cerr << get_fileline() << ": internal error: unhandled " "gate type." << endl; @@ -670,13 +731,18 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const cur[idx]->attribute(attrib_list[adx].key, attrib_list[adx].val); - cur[idx]->rise_time(rise_time); - cur[idx]->fall_time(fall_time); - cur[idx]->decay_time(decay_time); + /* The logic devices have some uniform processing. Then + all may have output delays and output drive strength. */ + if (NetLogic*log = dynamic_cast (cur[idx])) { + log->rise_time(rise_time); + log->fall_time(fall_time); + log->decay_time(decay_time); - cur[idx]->pin(0).drive0(drive_type(strength0())); - cur[idx]->pin(0).drive1(drive_type(strength1())); + log->pin(0).drive0(drive_type(strength0())); + log->pin(0).drive1(drive_type(strength1())); + } + cur[idx]->set_line(*this); des->add_node(cur[idx]); } diff --git a/emit.cc b/emit.cc index c52190684..079a41c84 100644 --- a/emit.cc +++ b/emit.cc @@ -165,6 +165,11 @@ bool NetUserFunc::emit_node(struct target_t*tgt) const return tgt->net_function(this); } +bool NetTran::emit_node(struct target_t*tgt) const +{ + return tgt->tran(this); +} + bool NetBUFZ::emit_node(struct target_t*tgt) const { return tgt->bufz(this); diff --git a/net_tran.cc b/net_tran.cc new file mode 100644 index 000000000..60be74ad2 --- /dev/null +++ b/net_tran.cc @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2008 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "config.h" + +# include + +# include +# include +# include "compiler.h" +# include "netlist.h" +# include "netmisc.h" +# include "ivl_assert.h" + +NetTran::NetTran(NetScope*scope, perm_string n, bool resistive, int enable) +: NetNode(scope, n, enable? 3 : 2) +{ + pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0); + pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0); + if (enable) { + pin(2).set_dir(Link::INPUT); + pin(2).set_name(perm_string::literal("E"), 0); + } +} + +NetTran::~NetTran() +{ +} diff --git a/netlist.h b/netlist.h index 691311301..da6bb196a 100644 --- a/netlist.h +++ b/netlist.h @@ -1359,6 +1359,20 @@ class NetSysFunc : public NetNode { const struct sfunc_return_type*def_; }; +class NetTran : public NetNode { + + public: + NetTran(NetScope*scope, perm_string n, bool resistive, int enable); + ~NetTran(); + + virtual void dump_node(ostream&, unsigned ind) const; + virtual bool emit_node(struct target_t*) const; + + private: + bool resistive_; + bool enable_; +}; + /* ========= * There are cases where expressions need to be represented. The * NetExpr class is the root of a hierarchy that serves that purpose. diff --git a/t-dll.cc b/t-dll.cc index c7c383342..4288f7477 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -1008,6 +1008,13 @@ void dll_target::logic(const NetLogic*net) scope_add_logic(scope, obj); } +bool dll_target::tran(const NetTran*net) +{ + cerr << net->get_fileline() << ": sorry: " + << "trans devices not supported." << endl; + return false; +} + bool dll_target::sign_extend(const NetSignExtend*net) { struct ivl_lpm_s*obj = new struct ivl_lpm_s; diff --git a/t-dll.h b/t-dll.h index 76b2443f5..ae0ce2986 100644 --- a/t-dll.h +++ b/t-dll.h @@ -67,6 +67,7 @@ struct dll_target : public target_t, public expr_scan_t { bool bufz(const NetBUFZ*); void event(const NetEvent*); void logic(const NetLogic*); + bool tran(const NetTran*); bool ureduce(const NetUReduce*); void net_case_cmp(const NetCaseCmp*); void udp(const NetUDP*); diff --git a/target.cc b/target.cc index 379a91754..e474c7cf7 100644 --- a/target.cc +++ b/target.cc @@ -61,6 +61,13 @@ void target_t::logic(const NetLogic*) "Unhandled logic gate" << endl; } +bool target_t::tran(const NetTran*) +{ + cerr << "target (" << typeid(*this).name() << "): " + << "TRAN devices not supported." << endl; + return false; +} + bool target_t::bufz(const NetBUFZ*) { cerr << "target (" << typeid(*this).name() << "): " diff --git a/target.h b/target.h index c68ffc2f0..d002a9797 100644 --- a/target.h +++ b/target.h @@ -86,6 +86,7 @@ struct target_t { /* Output a gate (called for each gate) */ virtual void logic(const NetLogic*); + virtual bool tran(const NetTran*); virtual bool ureduce(const NetUReduce*); /* unary reduction operator */ virtual bool bufz(const NetBUFZ*); virtual void udp(const NetUDP*);