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.
This commit is contained in:
steve 1998-11-09 18:55:33 +00:00
parent 9a93912ce7
commit ebad845fc3
15 changed files with 510 additions and 91 deletions

11
PExpr.h
View File

@ -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 <string>
@ -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.

View File

@ -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 <string>
@ -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.

View File

@ -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.

View File

@ -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<Module*>&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.

25
emit.cc
View File

@ -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.

View File

@ -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); }
<CSTRING>\\\" { yymore(); }

View File

@ -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 <cassert>
@ -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.
*

View File

@ -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.
*

39
parse.y
View File

@ -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);
}

View File

@ -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.

153
t-vvm.cc
View File

@ -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 <iostream>
# include <strstream>
# include <iomanip>
# include <string>
# include <typeinfo>
# 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<const NetNet*>(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 <<setw(indent_) << "" << mangle(sig->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.
*

View File

@ -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.

View File

@ -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.

View File

@ -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.
*

View File

@ -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 <string>
@ -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.
*