From ebad845fc357f521a82520cd9bcc9329a81749e9 Mon Sep 17 00:00:00 2001 From: steve Date: Mon, 9 Nov 1998 18:55:33 +0000 Subject: [PATCH] Add procedural while loops, Parse procedural for loops, Add procedural wait statements, Add constant nodes, Add XNOR logic gate, Make vvm output look a bit prettier. --- PExpr.h | 11 +++- Statement.h | 34 ++++++++++- design_dump.cc | 42 ++++++++++++-- elaborate.cc | 96 ++++++++++++++++++++++++++++--- emit.cc | 25 +++++++- lexor.lex | 4 +- netlist.cc | 13 ++++- netlist.h | 53 ++++++++++++++++- parse.y | 39 ++++++++++++- pform_dump.cc | 27 +++++++-- t-vvm.cc | 153 +++++++++++++++++++++++++++++++++++++++---------- target.cc | 23 +++++++- target.h | 12 +++- verinum.cc | 58 +++++++++---------- verinum.h | 11 +++- 15 files changed, 510 insertions(+), 91 deletions(-) diff --git a/PExpr.h b/PExpr.h index dcdff820e..7e21d88b5 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: PExpr.h,v 1.2 1998/11/07 17:05:05 steve Exp $" +#ident "$Id: PExpr.h,v 1.3 1998/11/09 18:55:33 steve Exp $" #endif # include @@ -84,6 +84,7 @@ class PENumber : public PExpr { const verinum& value() const { return *value_; } virtual void dump(ostream&) const; + virtual NetNet* elaborate_net(Design*des, const string&path) const; virtual NetExpr*elaborate_expr(Design*des, const string&path) const; virtual verinum* eval_const() const; @@ -138,6 +139,14 @@ class PEBinary : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.3 1998/11/09 18:55:33 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.2 1998/11/07 17:05:05 steve * Handle procedural conditional, and some * of the conditional expressions. diff --git a/Statement.h b/Statement.h index ad93b4290..783823a41 100644 --- a/Statement.h +++ b/Statement.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: Statement.h,v 1.2 1998/11/07 17:05:05 steve Exp $" +#ident "$Id: Statement.h,v 1.3 1998/11/09 18:55:33 steve Exp $" #endif # include @@ -198,6 +198,30 @@ class PEventStatement : public Statement { Statement*statement_; }; +class PForStatement : public Statement { + + public: + PForStatement(const string&n1, PExpr*e1, PExpr*cond, + const string&n2, PExpr*e2, Statement*st) + : name1_(n1), expr1_(e1), cond_(cond), name2_(n2), expr2_(e2), + statement_(st) + { } + + virtual NetProc* elaborate(Design*des, const string&path) const; + virtual void dump(ostream&out, unsigned ind) const; + + private: + string name1_; + PExpr* expr1_; + + PExpr*cond_; + + string name2_; + PExpr* expr2_; + + Statement*statement_; +}; + class PNoop : public Statement { public: @@ -206,6 +230,14 @@ class PNoop : public Statement { /* * $Log: Statement.h,v $ + * Revision 1.3 1998/11/09 18:55:33 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.2 1998/11/07 17:05:05 steve * Handle procedural conditional, and some * of the conditional expressions. diff --git a/design_dump.cc b/design_dump.cc index d4ac4cb5c..ab45f5c39 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: design_dump.cc,v 1.2 1998/11/07 17:05:05 steve Exp $" +#ident "$Id: design_dump.cc,v 1.3 1998/11/09 18:55:34 steve Exp $" #endif /* @@ -115,6 +115,12 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const dump_node_pins(o, ind+4); } +void NetConst::dump_node(ostream&o, unsigned ind) const +{ + o << setw(ind) << "" << "constant " << value_ << ": " << name() << endl; + dump_node_pins(o, ind+4); +} + void NetLogic::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "logic: "; @@ -134,6 +140,9 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const case OR: o << "or"; break; + case XNOR: + o << "xnor"; + break; case XOR: o << "xor"; break; @@ -157,6 +166,9 @@ void NetPEvent::dump_node(ostream&o, unsigned ind) const case NEGEDGE: o << "negedge "; break; + case POSITIVE: + o << "positive "; + break; } o << name() << endl; @@ -222,16 +234,19 @@ void NetPDelay::dump(ostream&o, unsigned ind) const void NetPEvent::dump(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "@"; + o << setw(ind) << "" ; switch (edge_) { case NEGEDGE: - o << "(negedge " << name() << ")"; + o << "@" << "(negedge " << name() << ")"; break; case POSEDGE: - o << "(posedge " << name() << ")"; + o << "@" << "(posedge " << name() << ")"; break; case ANYEDGE: - o << name(); + o << "@" << name(); + break; + case POSITIVE: + o << "wait (" << name() << ")"; break; } o << endl; @@ -261,6 +276,12 @@ void NetTask::dump(ostream&o, unsigned ind) const o << ";" << endl; } +void NetWhile::dump(ostream&o, unsigned ind) const +{ + o << setw(ind) << "" << "while (" << *cond_ << ")" << endl; + proc_->dump(o, ind+3); +} + /* Dump a statement type that someone didn't write a dump for. */ void NetProc::dump(ostream&o, unsigned ind) const { @@ -285,6 +306,9 @@ void NetEBinary::dump(ostream&o) const case 'e': o << "=="; break; + case 'n': + o << "!="; + break; } o << "("; right_->dump(o); @@ -351,6 +375,14 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.3 1998/11/09 18:55:34 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.2 1998/11/07 17:05:05 steve * Handle procedural conditional, and some * of the conditional expressions. diff --git a/elaborate.cc b/elaborate.cc index ca5d6018c..ca981b64e 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: elaborate.cc,v 1.2 1998/11/07 17:05:05 steve Exp $" +#ident "$Id: elaborate.cc,v 1.3 1998/11/09 18:55:34 steve Exp $" #endif /* @@ -149,25 +149,31 @@ void PGAssign::elaborate(Design*des, const string&path) const void PGBuiltin::elaborate(Design*des, const string&path) const { NetLogic*cur = 0; + string name = get_name(); + if (name == "") + name = local_symbol(path); switch (type()) { case AND: - cur = new NetLogic(get_name(), pin_count(), NetLogic::AND); + cur = new NetLogic(name, pin_count(), NetLogic::AND); break; case NAND: - cur = new NetLogic(get_name(), pin_count(), NetLogic::NAND); + cur = new NetLogic(name, pin_count(), NetLogic::NAND); break; case NOR: - cur = new NetLogic(get_name(), pin_count(), NetLogic::NOR); + cur = new NetLogic(name, pin_count(), NetLogic::NOR); break; case NOT: - cur = new NetLogic(get_name(), pin_count(), NetLogic::NOT); + cur = new NetLogic(name, pin_count(), NetLogic::NOT); break; case OR: - cur = new NetLogic(get_name(), pin_count(), NetLogic::OR); + cur = new NetLogic(name, pin_count(), NetLogic::OR); + break; + case XNOR: + cur = new NetLogic(name, pin_count(), NetLogic::XNOR); break; case XOR: - cur = new NetLogic(get_name(), pin_count(), NetLogic::XOR); + cur = new NetLogic(name, pin_count(), NetLogic::XOR); break; } @@ -225,6 +231,9 @@ void PGModule::elaborate(Design*des, const string&path) const assert(pin_count() == rmod->ports.size()); for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { + // Skip unconnected module ports. + if (pin(idx) == 0) + continue; NetNet*sig = pin(idx)->elaborate_net(des, path); if (sig == 0) { cerr << "Expression too complicated for elaboration." << endl; @@ -311,6 +320,19 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path) const des->add_node(gate); break; + case 'e': // == + assert(lsig->pin_count() == 1); + assert(rsig->pin_count() == 1); + gate = new NetLogic(local_symbol(path), 3, NetLogic::XNOR); + connect(gate->pin(1), lsig->pin(0)); + connect(gate->pin(2), rsig->pin(0)); + osig = new NetNet(local_symbol(path), NetNet::WIRE); + osig->local_flag(true); + connect(gate->pin(0), osig->pin(0)); + des->add_signal(osig); + des->add_node(gate); + break; + default: cerr << "Unhandled BINARY '" << op_ << "'" << endl; osig = 0; @@ -363,6 +385,21 @@ NetNet* PEIdent::elaborate_net(Design*des, const string&path) const return sig; } +/* + * XXXX For now, only generate a single bit. I am going to have to add + * code to properly calculate expression bit widths, eventually. + */ +NetNet* PENumber::elaborate_net(Design*des, const string&path) const +{ + NetNet*net = new NetNet(local_symbol(path), NetNet::IMPLICIT); + net->local_flag(true); + NetConst*tmp = new NetConst(local_symbol(path), value_->get(0)); + des->add_node(tmp); + des->add_signal(net); + connect(net->pin(0), tmp->pin(0)); + return net; +} + NetNet* PEUnary::elaborate_net(Design*des, const string&path) const { NetNet* sub_sig = expr_->elaborate_net(des, path); @@ -449,7 +486,8 @@ NetExpr* PEUnary::elaborate_expr(Design*des, const string&path) const NetProc* Statement::elaborate(Design*des, const string&path) const { - cerr << "What kind of statement? " << typeid(*this).name() << endl; + cerr << "elaborate: What kind of statement? " << + typeid(*this).name() << endl; NetProc*cur = new NetProc; return cur; } @@ -540,6 +578,40 @@ NetProc* PEventStatement::elaborate(Design*des, const string&path) const return ev; } +/* + * elaborate the for loop as the equivilent while loop. This eases the + * task for the target code generator. The structure is: + * + * begin + * name1_ = expr1_; + * while (cond_) begin + * statement_; + * name2_ = expr2_; + * end + * end + */ +NetProc* PForStatement::elaborate(Design*des, const string&path) const +{ + NetBlock*top = new NetBlock(NetBlock::SEQU); + NetNet*sig = des->find_signal(path+"."+name1_); + assert(sig); + NetAssign*init = new NetAssign(sig, expr1_->elaborate_expr(des, path)); + top->append(init); + + NetBlock*body = new NetBlock(NetBlock::SEQU); + + body->append(statement_->elaborate(des, path)); + + sig = des->find_signal(path+"."+name2_); + assert(sig); + NetAssign*step = new NetAssign(sig, expr2_->elaborate_expr(des, path)); + body->append(step); + + NetWhile*loop = new NetWhile(cond_->elaborate_expr(des, path), body); + top->append(loop); + return top; +} + void Module::elaborate(Design*des, const string&path) const { // Get all the explicitly declared wires of the module and @@ -618,6 +690,14 @@ Design* elaborate(const list&modules, const string&root) /* * $Log: elaborate.cc,v $ + * Revision 1.3 1998/11/09 18:55:34 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.2 1998/11/07 17:05:05 steve * Handle procedural conditional, and some * of the conditional expressions. diff --git a/emit.cc b/emit.cc index 90af5d706..32e10991e 100644 --- a/emit.cc +++ b/emit.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: emit.cc,v 1.2 1998/11/07 17:05:05 steve Exp $" +#ident "$Id: emit.cc,v 1.3 1998/11/09 18:55:34 steve Exp $" #endif /* @@ -45,6 +45,11 @@ void NetAssign::emit_node(ostream&o, struct target_t*tgt) const tgt->net_assign(o, this); } +void NetConst::emit_node(ostream&o, struct target_t*tgt) const +{ + tgt->net_const(o, this); +} + void NetPEvent::emit_node(ostream&o, struct target_t*tgt) const { tgt->net_pevent(o, this); @@ -109,6 +114,11 @@ void NetTask::emit_proc(ostream&o, struct target_t*tgt) const tgt->proc_task(o, this); } +void NetWhile::emit_proc(ostream&o, struct target_t*tgt) const +{ + tgt->proc_while(o, this); +} + void NetBlock::emit_recurse(ostream&o, struct target_t*tgt) const { if (last_ == 0) @@ -133,6 +143,11 @@ void NetCondit::emit_recurse_else(ostream&o, struct target_t*tgt) const else_->emit_proc(o, tgt); } +void NetWhile::emit_proc_recurse(ostream&o, struct target_t*tgt) const +{ + proc_->emit_proc(o, tgt); +} + void Design::emit(ostream&o, struct target_t*tgt) const { tgt->start_design(o, this); @@ -203,6 +218,14 @@ void emit(ostream&o, const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.3 1998/11/09 18:55:34 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.2 1998/11/07 17:05:05 steve * Handle procedural conditional, and some * of the conditional expressions. diff --git a/lexor.lex b/lexor.lex index 571471b77..fccbb28ff 100644 --- a/lexor.lex +++ b/lexor.lex @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: lexor.lex,v 1.2 1998/11/07 17:05:05 steve Exp $" +#ident "$Id: lexor.lex,v 1.3 1998/11/09 18:55:34 steve Exp $" #endif //# define YYSTYPE lexval @@ -68,7 +68,7 @@ static verinum*make_sized_hex(const char*txt); "===" { return K_CEQ; } "!==" { return K_CNE; } -[;:\[\],()#=.@&!<|^~+-] { return yytext[0]; } +[;:\[\],()#=.@&!<|^~+*/-] { return yytext[0]; } \" { BEGIN(CSTRING); } \\\" { yymore(); } diff --git a/netlist.cc b/netlist.cc index ed67075f8..9482d619c 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: netlist.cc,v 1.3 1998/11/07 19:17:10 steve Exp $" +#ident "$Id: netlist.cc,v 1.4 1998/11/09 18:55:34 steve Exp $" #endif # include @@ -149,7 +149,9 @@ NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r) : op_(op), left_(l), right_(r) { switch (op_) { + // comparison operators return a 1-bin wide result. case 'e': + case 'n': expr_width(1); break; default: @@ -178,6 +180,7 @@ void NetEBinary::set_width(unsigned w) op_ << "." << endl; case '+': + case '-': left_->set_width(w); right_->set_width(w); expr_width(w); @@ -317,6 +320,14 @@ void Design::add_process(NetProcTop*pro) /* * $Log: netlist.cc,v $ + * Revision 1.4 1998/11/09 18:55:34 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.3 1998/11/07 19:17:10 steve * Calculate expression widths at elaboration time. * diff --git a/netlist.h b/netlist.h index 20a41edc1..2b87955c6 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: netlist.h,v 1.3 1998/11/07 19:17:10 steve Exp $" +#ident "$Id: netlist.h,v 1.4 1998/11/09 18:55:34 steve Exp $" #endif /* @@ -252,13 +252,28 @@ class NetBUFZ : public NetNode { virtual void emit_node(ostream&, struct target_t*) const; }; +class NetConst : public NetNode { + + public: + explicit NetConst(const string&n, verinum::V v) + : NetNode(n, 1), value_(v) { } + + verinum::V value() const { return value_; } + + virtual void emit_node(ostream&, struct target_t*) const; + virtual void dump_node(ostream&, unsigned ind) const; + + private: + verinum::V value_; +}; + /* * This class represents all manner of logic gates. */ class NetLogic : public NetNode { public: - enum TYPE { AND, NAND, NOR, NOT, OR, XOR }; + enum TYPE { AND, NAND, NOR, NOT, OR, XNOR, XOR }; explicit NetLogic(const string&n, unsigned pins, TYPE t) : NetNode(n, pins), type_(t) { } @@ -390,7 +405,7 @@ class NetPDelay : public NetProc { class NetPEvent : public NetProc, public NetNode { public: - enum Type { ANYEDGE, POSEDGE, NEGEDGE }; + enum Type { ANYEDGE, POSEDGE, NEGEDGE, POSITIVE }; public: NetPEvent(const string&ev, Type ed, NetProc*st) @@ -448,6 +463,30 @@ class NetTask : public NetProc { NetExpr**parms_; }; +/* + * The while statement is a condition that is tested in the front of + * each iteration, and a statement (a NetProc) that is executed as + * long as the condition is true. + */ +class NetWhile : public NetProc { + + public: + NetWhile(NetExpr*c, NetProc*p) + : cond_(c), proc_(p) { } + + NetExpr*expr() const { return cond_; } + + void emit_proc_recurse(ostream&, struct target_t*) const; + + virtual void emit_proc(ostream&, struct target_t*) const; + virtual void dump(ostream&, unsigned ind) const; + + private: + NetExpr*cond_; + NetProc*proc_; +}; + + /* The is the top of any process. It carries the type (initial or always) and a pointer to the statement, probably a block, that makes up the process. */ @@ -670,6 +709,14 @@ inline ostream& operator << (ostream&o, const NetExpr&exp) /* * $Log: netlist.h,v $ + * Revision 1.4 1998/11/09 18:55:34 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.3 1998/11/07 19:17:10 steve * Calculate expression widths at elaboration time. * diff --git a/parse.y b/parse.y index 30ef1142f..77e0435ee 100644 --- a/parse.y +++ b/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: parse.y,v 1.2 1998/11/07 17:05:05 steve Exp $" +#ident "$Id: parse.y,v 1.3 1998/11/09 18:55:34 steve Exp $" #endif # include "parse_misc.h" @@ -177,6 +177,9 @@ expression | expression '+' expression { $$ = new PEBinary('+', $1, $3); } + | expression '-' expression + { $$ = new PEBinary('-', $1, $3); + } | expression '&' expression { $$ = new PEBinary('&', $1, $3); } @@ -530,6 +533,34 @@ statement { yyerror(@1, "Malformed conditional expression."); $$ = $5; } + | K_for '(' lvalue '=' expression ';' expression ';' + lvalue '=' expression ')' statement + { $$ = new PForStatement(*$3, $5, $7, *$9, $11, $13); + delete $3; + delete $9; + } + | K_for '(' lvalue '=' expression ';' expression ';' + error ')' statement + { $$ = 0; + yyerror(@9, "Error in for loop step assigment."); + } + | K_for '(' lvalue '=' expression ';' error ';' + lvalue '=' expression ')' statement + { $$ = 0; + yyerror(@7, "Error in for loop condition expression."); + } + | K_for '(' error ')' statement + { $$ = 0; + yyerror(@3, "Incomprehensible for loop."); + } + | K_while '(' expression ')' statement + { $$ = 0; + yyerror(@1, "Sorry, while loops not implemented."); + } + | K_while '(' error ')' statement + { $$ = 0; + yyerror(@3, "Error in while loop condition."); + } | delay statement_opt { PDelayStatement*tmp = new PDelayStatement($1, $2); $$ = tmp; @@ -546,6 +577,12 @@ statement { $$ = pform_make_assignment($1, $3); yyerror(@1, "Sorry, non-blocking assignment not implemented."); } + | K_wait '(' expression ')' statement_opt + { PEventStatement*tmp; + tmp = new PEventStatement(NetPEvent::POSITIVE, $3); + tmp->set_statement($5); + $$ = tmp; + } | SYSTEM_IDENTIFIER '(' expression_list ')' ';' { $$ = pform_make_calltask($1, $3); } diff --git a/pform_dump.cc b/pform_dump.cc index 9c65e7679..2904f138b 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pform_dump.cc,v 1.2 1998/11/07 17:05:06 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.3 1998/11/09 18:55:34 steve Exp $" #endif /* @@ -105,9 +105,6 @@ void PWire::dump(ostream&out) const case NetNet::REG: out << " reg "; break; - default: - out << " (" << type << ") "; - break; } switch (port_type) { @@ -141,7 +138,8 @@ void PGate::dump_pins(ostream&out) const out << *pin(0); for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) { - out << ", " << *pin(idx); + out << ", "; + if (pin(idx)) out << *pin(idx); } } } @@ -256,12 +254,23 @@ void PEventStatement::dump(ostream&out, unsigned ind) const case NetPEvent::NEGEDGE: out << "negedge "; break; + case NetPEvent::POSITIVE: + out << "positive "; + break; } out << *expr_ << ")" << endl; statement_->dump(out, ind+2); } +void PForStatement::dump(ostream&out, unsigned ind) const +{ + out << setw(ind) << "" << "for (" << name1_ << " = " << *expr1_ + << "; " << *cond_ << "; " << name2_ << " = " << *expr2_ << + ")" << endl; + statement_->dump(out, ind+3); +} + void PProcess::dump(ostream&out, unsigned ind) const { switch (type_) { @@ -314,6 +323,14 @@ void pform_dump(ostream&out, Module*mod) /* * $Log: pform_dump.cc,v $ + * Revision 1.3 1998/11/09 18:55:34 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.2 1998/11/07 17:05:06 steve * Handle procedural conditional, and some * of the conditional expressions. diff --git a/t-vvm.cc b/t-vvm.cc index 06a372a6e..5f1679bc7 100644 --- a/t-vvm.cc +++ b/t-vvm.cc @@ -17,11 +17,12 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: t-vvm.cc,v 1.3 1998/11/07 19:17:10 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.4 1998/11/09 18:55:34 steve Exp $" #endif # include # include +# include # include # include # include "netlist.h" @@ -42,12 +43,14 @@ class target_vvm : public target_t { virtual void signal(ostream&os, const NetNet*); virtual void logic(ostream&os, const NetLogic*); virtual void bufz(ostream&os, const NetBUFZ*); + virtual void net_const(ostream&os, const NetConst*); virtual void net_pevent(ostream&os, const NetPEvent*); virtual void start_process(ostream&os, const NetProcTop*); virtual void proc_assign(ostream&os, const NetAssign*); virtual void proc_block(ostream&os, const NetBlock*); virtual void proc_condit(ostream&os, const NetCondit*); virtual void proc_task(ostream&os, const NetTask*); + virtual void proc_while(ostream&os, const NetWhile*); virtual void proc_event(ostream&os, const NetPEvent*); virtual void proc_delay(ostream&os, const NetPDelay*); virtual void end_process(ostream&os, const NetProcTop*); @@ -57,8 +60,11 @@ class target_vvm : public target_t { void emit_gate_outputfun_(const NetNode*); ostrstream delayed; + ostrstream init_code; unsigned process_counter; unsigned thread_step_; + + unsigned indent_; }; /* @@ -69,13 +75,14 @@ class target_vvm : public target_t { class vvm_proc_rval : public expr_scan_t { public: - explicit vvm_proc_rval(ostream&os) - : result(""), os_(os) { } + explicit vvm_proc_rval(ostream&os, unsigned i) + : result(""), os_(os), indent_(i) { } string result; private: ostream&os_; + unsigned indent_; private: virtual void expr_const(const NetEConst*); @@ -88,10 +95,10 @@ class vvm_proc_rval : public expr_scan_t { void vvm_proc_rval::expr_const(const NetEConst*expr) { string tname = make_temp(); - os_ << " vvm_bitset_t<" << expr->expr_width() << "> " - << tname << ";" << endl; + os_ << setw(indent_) << "" << "vvm_bitset_t<" << + expr->expr_width() << "> " << tname << ";" << endl; for (unsigned idx = 0 ; idx < expr->expr_width() ; idx += 1) { - os_ << " " << tname << "[" << idx << "] = "; + os_ << setw(indent_) << "" << tname << "[" << idx << "] = "; switch (expr->value().get(idx)) { case verinum::V0: os_ << "V0"; @@ -153,16 +160,24 @@ void vvm_proc_rval::expr_binary(const NetEBinary*expr) string rres = result; result = make_temp(); - os_ << " vvm_bitset_t<" << expr->expr_width() << ">" << - result << ";" << endl; + os_ << setw(indent_) << "" << "vvm_bitset_t<" << + expr->expr_width() << ">" << result << ";" << endl; switch (expr->op()) { case 'e': - os_ << " " << result << " = vvm_binop_eq(" << lres - << "," << rres << ");" << endl; + os_ << setw(indent_) << "" << result << " = vvm_binop_eq(" + << lres << "," << rres << ");" << endl; + break; + case 'n': + os_ << setw(indent_) << "" << result << " = vvm_binop_ne(" + << lres << "," << rres << ");" << endl; break; case '+': - os_ << " " << result << " = vvm_binop_plus(" << lres - << "," << rres << ");" << endl; + os_ << setw(indent_) << "" << result << " = vvm_binop_plus(" + << lres << "," << rres << ");" << endl; + break; + case '-': + os_ << setw(indent_) << "" << result << " = vvm_binop_minus(" + << lres << "," << rres << ");" << endl; break; default: cerr << "vvm: Unhandled binary op `" << expr->op() << "': " @@ -173,9 +188,9 @@ void vvm_proc_rval::expr_binary(const NetEBinary*expr) } } -static string emit_proc_rval(ostream&os, const NetExpr*expr) +static string emit_proc_rval(ostream&os, unsigned indent, const NetExpr*expr) { - vvm_proc_rval scan (os); + vvm_proc_rval scan (os, indent); expr->expr_scan(&scan); return scan.result; } @@ -254,6 +269,9 @@ void target_vvm::end_design(ostream&os, const Design*mod) os << "main()" << endl << "{" << endl; os << " vvm_simulation sim;" << endl; + init_code << ends; + os << init_code.str(); + for (unsigned idx = 0 ; idx < process_counter ; idx += 1) os << " thread" << (idx+1) << "_t thread_" << (idx+1) << "(&sim);" << endl; @@ -333,6 +351,10 @@ void target_vvm::logic(ostream&os, const NetLogic*gate) os << "static vvm_or" << "<" << gate->pin_count()-1 << "," << gate->delay1() << "> "; break; + case NetLogic::XNOR: + os << "static vvm_xnor" << "<" << gate->pin_count()-1 << + "," << gate->delay1() << "> "; + break; case NetLogic::XOR: os << "static vvm_xor" << "<" << gate->pin_count()-1 << "," << gate->delay1() << "> "; @@ -356,6 +378,41 @@ void target_vvm::bufz(ostream&os, const NetBUFZ*gate) emit_gate_outputfun_(gate); } +/* + * The NetConst is a synthetic device created to represent constant + * values. I represent them in the output as a vvm_bufz object that + * has its input connected to nothing but is initialized to the + * desired constant value. + */ +void target_vvm::net_const(ostream&os, const NetConst*gate) +{ + os << "static void " << mangle(gate->name()) << + "_output_fun(vvm_simulation*, vvm_bit_t);" << endl; + + os << "static vvm_bufz " << mangle(gate->name()) << "(&" << + mangle(gate->name()) << "_output_fun);" << endl; + + init_code << " " << mangle(gate->name()) << ".set(&sim, 1, "; + switch (gate->value()) { + case verinum::V0: + init_code << "V0"; + break; + case verinum::V1: + init_code << "V1"; + break; + case verinum::Vx: + init_code << "Vx"; + break; + case verinum::Vz: + init_code << "Vz"; + break; + } + init_code << ");" << endl; + + + emit_gate_outputfun_(gate); +} + /* * The net_pevent device is a synthetic device type--a fabrication of * the elaboration phase. An event device receives value changes from @@ -375,6 +432,7 @@ void target_vvm::net_pevent(ostream&os, const NetPEvent*gate) void target_vvm::start_process(ostream&os, const NetProcTop*proc) { process_counter += 1; + indent_ = 8; thread_step_ = 0; os << "class thread" << process_counter << @@ -402,16 +460,16 @@ void target_vvm::start_process(ostream&os, const NetProcTop*proc) */ void target_vvm::proc_assign(ostream&os, const NetAssign*net) { - string rval = emit_proc_rval(os, net->rval()); + string rval = emit_proc_rval(os, indent_, net->rval()); - os << " // " << net->lval()->name() << " = "; + os << setw(indent_) << "" << "// " << net->lval()->name() << " = "; net->rval()->dump(os); os << endl; - os << " " << mangle(net->lval()->name()) << " = " << rval << - ";" << endl; + os << setw(indent_) << "" << mangle(net->lval()->name()) << " = " + << rval << ";" << endl; - os << " " << mangle(net->lval()->name()) << + os << setw(indent_) << "" << mangle(net->lval()->name()) << "_mon.trigger(sim_);" << endl; @@ -430,14 +488,14 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net) continue; if (const NetNet*sig = dynamic_cast(cur)) { - os << " " << mangle(sig->name()) << "[" << - pin << "] = " << rval << "[" << idx << - "];" << endl; - os << " " << mangle(sig->name()) << - "_mon.trigger(sim_);" << endl; + os << setw(indent_) << "" << mangle(sig->name()) + << "[" << pin << "] = " << rval << "[" << idx + << "];" << endl; + os <name()) + << "_mon.trigger(sim_);" << endl; } else { - os << " " << mangle(cur->name()) << + os << setw(indent_) << "" << mangle(cur->name()) << ".set(sim_, " << pin << ", " << rval << "[" << idx << "]);" << endl; } @@ -452,12 +510,17 @@ void target_vvm::proc_block(ostream&os, const NetBlock*net) void target_vvm::proc_condit(ostream&os, const NetCondit*net) { - string expr = emit_proc_rval(os, net->expr()); - os << " if (" << expr << "[0] == V1) {" << endl; + unsigned ind = indent_; + indent_ += 4; + + string expr = emit_proc_rval(os, indent_, net->expr()); + os << setw(ind) << "" << "if (" << expr << "[0] == V1) {" << endl; net->emit_recurse_if(os, this); - os << " } else {" << endl; + os << setw(ind) << "" << "} else {" << endl; net->emit_recurse_else(os, this); - os << " }" << endl; + os << setw(ind) << "" << "}" << endl; + + indent_ = ind; } void target_vvm::proc_task(ostream&os, const NetTask*net) @@ -479,6 +542,21 @@ void target_vvm::proc_task(ostream&os, const NetTask*net) } } +void target_vvm::proc_while(ostream&os, const NetWhile*net) +{ + unsigned ind = indent_; + indent_ += 4; + + os << setw(ind) << "" << "for (;;) {" << endl; + string expr = emit_proc_rval(os, indent_, net->expr()); + os << setw(indent_) << "" << "if (" << expr << "[0] != V1)" + " break;" << endl; + net->emit_proc_recurse(os, this); + os << setw(ind) << "" << "}" << endl; + + indent_ = ind; +} + /* * Within a process, the proc_event is a statement that is blocked * until the event is signalled. @@ -486,8 +564,10 @@ void target_vvm::proc_task(ostream&os, const NetTask*net) void target_vvm::proc_event(ostream&os, const NetPEvent*proc) { thread_step_ += 1; - os << " step_ = &step_" << thread_step_ << "_;" << endl; - os << " " << mangle(proc->name()) << ".wait(vvm_pevent::"; + os << setw(indent_) << "" << "step_ = &step_" << thread_step_ << + "_;" << endl; + os << setw(indent_) << "" << mangle(proc->name()) << + ".wait(vvm_pevent::"; switch (proc->edge()) { case NetPEvent::ANYEDGE: os << "ANYEDGE"; @@ -498,6 +578,9 @@ void target_vvm::proc_event(ostream&os, const NetPEvent*proc) case NetPEvent::NEGEDGE: os << "NEGEDGE"; break; + case NetPEvent::POSITIVE: + os << "POSITIVE"; + break; } os << ", this);" << endl; os << " }" << endl; @@ -545,6 +628,14 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.4 1998/11/09 18:55:34 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.3 1998/11/07 19:17:10 steve * Calculate expression widths at elaboration time. * diff --git a/target.cc b/target.cc index 8326b0332..60e0b73cc 100644 --- a/target.cc +++ b/target.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: target.cc,v 1.2 1998/11/07 17:05:06 steve Exp $" +#ident "$Id: target.cc,v 1.3 1998/11/09 18:55:34 steve Exp $" #endif # include "target.h" @@ -49,6 +49,12 @@ void target_t::net_assign(ostream&os, const NetAssign*) { } +void target_t::net_const(ostream&os, const NetConst*) +{ + cerr << "target (" << typeid(*this).name() << "): " + "Unhandled CONSTANT node." << endl; +} + void target_t::net_pevent(ostream&os, const NetPEvent*) { cerr << "target (" << typeid(*this).name() << "): " @@ -90,6 +96,13 @@ void target_t::proc_task(ostream&os, const NetTask*) { } +void target_t::proc_while(ostream&os, const NetWhile*net) +{ + cerr << "target (" << typeid(*this).name() << "): " + "Unhandled while:" << endl; + net->dump(cerr, 6); +} + void target_t::end_process(ostream&os, const NetProcTop*) { } @@ -134,6 +147,14 @@ void expr_scan_t::expr_binary(const NetEBinary*ex) /* * $Log: target.cc,v $ + * Revision 1.3 1998/11/09 18:55:34 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.2 1998/11/07 17:05:06 steve * Handle procedural conditional, and some * of the conditional expressions. diff --git a/target.h b/target.h index e3f25b247..9ad910348 100644 --- a/target.h +++ b/target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: target.h,v 1.2 1998/11/07 17:05:06 steve Exp $" +#ident "$Id: target.h,v 1.3 1998/11/09 18:55:35 steve Exp $" #endif # include "netlist.h" @@ -62,6 +62,7 @@ struct target_t { virtual void logic(ostream&os, const NetLogic*); virtual void bufz(ostream&os, const NetBUFZ*); virtual void net_assign(ostream&os, const NetAssign*); + virtual void net_const(ostream&os, const NetConst*); virtual void net_pevent(ostream&os, const NetPEvent*); /* Output a process (called for each process) */ @@ -72,6 +73,7 @@ struct target_t { virtual void proc_block(ostream&os, const NetBlock*); virtual void proc_condit(ostream&os, const NetCondit*); virtual void proc_task(ostream&os, const NetTask*); + virtual void proc_while(ostream&os, const NetWhile*); virtual void proc_event(ostream&os, const NetPEvent*); virtual void proc_delay(ostream&os, const NetPDelay*); @@ -111,6 +113,14 @@ extern const struct target *target_table[]; /* * $Log: target.h,v $ + * Revision 1.3 1998/11/09 18:55:35 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.2 1998/11/07 17:05:06 steve * Handle procedural conditional, and some * of the conditional expressions. diff --git a/verinum.cc b/verinum.cc index c50d3873f..1a37e60ea 100644 --- a/verinum.cc +++ b/verinum.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: verinum.cc,v 1.2 1998/11/07 17:04:48 steve Exp $" +#ident "$Id: verinum.cc,v 1.3 1998/11/09 18:55:35 steve Exp $" #endif # include "verinum.h" @@ -162,6 +162,24 @@ string verinum::as_string() const return result; } +ostream& operator<< (ostream&o, verinum::V v) +{ + switch (v) { + case verinum::V0: + o << "0"; + break; + case verinum::V1: + o << "1"; + break; + case verinum::Vx: + o << "x"; + break; + case verinum::Vz: + o << "z"; + break; + } +} + ostream& operator<< (ostream&o, const verinum&v) { o << v.len() << "'b"; @@ -178,36 +196,10 @@ ostream& operator<< (ostream&o, const verinum&v) if (trim_left != v.get(idx-1)) break; - switch (trim_left) { - case verinum::V0: - o << "0"; - break; - case verinum::V1: - o << "1"; - break; - case verinum::Vx: - o << "x"; - break; - case verinum::Vz: - o << "z"; - break; - } + o << trim_left; while (idx > 0) { - switch (v.get(idx-1)) { - case verinum::V0: - o << "0"; - break; - case verinum::V1: - o << "1"; - break; - case verinum::Vx: - o << "x"; - break; - case verinum::Vz: - o << "z"; - break; - } + o << v.get(idx-1); idx -= 1; } @@ -216,6 +208,14 @@ ostream& operator<< (ostream&o, const verinum&v) /* * $Log: verinum.cc,v $ + * Revision 1.3 1998/11/09 18:55:35 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.2 1998/11/07 17:04:48 steve * Properly dump 0 length numbers. * diff --git a/verinum.h b/verinum.h index 2bf903921..d25655356 100644 --- a/verinum.h +++ b/verinum.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: verinum.h,v 1.1 1998/11/03 23:29:08 steve Exp $" +#ident "$Id: verinum.h,v 1.2 1998/11/09 18:55:35 steve Exp $" #endif # include @@ -74,9 +74,18 @@ class verinum { class ostream; ostream& operator<< (ostream&, const verinum&); +ostream& operator<< (ostream&, verinum::V); /* * $Log: verinum.h,v $ + * Revision 1.2 1998/11/09 18:55:35 steve + * Add procedural while loops, + * Parse procedural for loops, + * Add procedural wait statements, + * Add constant nodes, + * Add XNOR logic gate, + * Make vvm output look a bit prettier. + * * Revision 1.1 1998/11/03 23:29:08 steve * Introduce verilog to CVS. *