NetAssign handles lvalues as pin links

instead of a signal pointer,
 Wire attributes added,
 Ability to parse UDP descriptions added,
 XNF generates EXT records for signals with
 the PAD attribute.
This commit is contained in:
steve 1998-11-23 00:20:22 +00:00
parent 338240c37b
commit af8d6fbf01
14 changed files with 494 additions and 43 deletions

13
PWire.h
View File

@ -19,10 +19,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PWire.h,v 1.1 1998/11/03 23:28:55 steve Exp $"
#ident "$Id: PWire.h,v 1.2 1998/11/23 00:20:22 steve Exp $"
#endif
# include "netlist.h"
# include <map>
class ostream;
class PExpr;
class Design;
@ -46,6 +47,8 @@ class PWire {
PExpr*msb;
PExpr*lsb;
map<string,string> attributes;
// Write myself to the specified stream.
void dump(ostream&out) const;
@ -58,6 +61,14 @@ class PWire {
/*
* $Log: PWire.h,v $
* Revision 1.2 1998/11/23 00:20:22 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.1 1998/11/03 23:28:55 steve
* Introduce verilog to CVS.
*

View File

@ -1,4 +1,13 @@
THE ICARUS VERILOG COMPILATION SYSTEM
This tool includes a parser that parses Verilog (plus extensions) and
generates an internal netlist. The netlist is passed to various
processing steps that transform the design to more optimal/practical
forms, then passed to a code generator for final output. The
processing steps and the code generator are selected by command line
switches.
INVOKING
The vl command is the compiler driver, that invokes the parser,
@ -42,6 +51,23 @@ Usage: vl [-s <module>] [-o <file>] [-D] [-F <name>] [-t <name>] file
Select the output format for the compiled result. Use the
"vl -h" command to get a list of configured targets.
ATTRIBUTES
The parser accepts as an extension to Verilog the $attribute module
item. The syntax of the $attribute item is:
$attribute (<identifier>, <key>, <value>);
The $attribute keyword looks like a system task invocation. The
difference here is that the parameters are more restricted then those
of a system task. The <identifier> must be an identifier. This will be
the item to get an attribute. The <key> and <value> are strings, not
expressions, that give the key and the value of the attribute to be
attached to the identified object.
Attributes are [<key> <value>] pairs and are used to communicate with
the various processing steps. See the documentation for the processing
step for a list of the pertinent attributes.
HOW IT WORKS -- STAGES OF PROCESSING

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.3 1998/11/09 18:55:34 steve Exp $"
#ident "$Id: design_dump.cc,v 1.4 1998/11/23 00:20:22 steve Exp $"
#endif
/*
@ -66,6 +66,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << " (local)";
o << " #(" << delay1() << "," << delay2() << "," << delay3() <<
")" << endl;
dump_obj_attr(o, ind+4);
}
@ -80,6 +81,7 @@ void NetNode::dump_node(ostream&o, unsigned ind) const
<< endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
/* This is the generic dumping of all the signals connected to each
@ -103,6 +105,16 @@ void NetObj::dump_node_pins(ostream&o, unsigned ind) const
}
}
void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
{
for (map<string,string>::const_iterator idx = attributes_.begin()
; idx != attributes_.end()
; idx ++) {
o << setw(ind) << "" << (*idx).first << " = \"" <<
(*idx).second << "\"" << endl;
}
}
void NetAssign::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Procedural assign: " << *rval_ << endl;
@ -193,7 +205,16 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
/* Dump an assignment statement */
void NetAssign::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << lval_->name() << " = ";
o << setw(ind) << "";
NetNet*sig;
unsigned msb, lsb;
find_lval_range(sig, msb, lsb);
o << sig->name() << "[" << msb;
if (pin_count() > 1)
o << ":" << lsb;
o << "] = ";
rval_->dump(o);
o << ";" << endl;
}
@ -375,6 +396,14 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.4 1998/11/23 00:20:22 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.3 1998/11/09 18:55:34 steve
* Add procedural while loops,
* Parse procedural for loops,

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.5 1998/11/21 19:19:44 steve Exp $"
#ident "$Id: elaborate.cc,v 1.6 1998/11/23 00:20:22 steve Exp $"
#endif
/*
@ -125,6 +125,7 @@ void PWire::elaborate(Design*des, const string&path) const
NetNet*sig = new NetNet(path + "." + name, wtype, wid);
sig->port_type(port_type);
sig->set_attributes(attributes);
des->add_signal(sig);
}
@ -706,6 +707,14 @@ Design* elaborate(const list<Module*>&modules, const string&root)
/*
* $Log: elaborate.cc,v $
* Revision 1.6 1998/11/23 00:20:22 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.5 1998/11/21 19:19:44 steve
* Give anonymous modules a name when elaborated.
*

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.3 1998/11/09 18:55:34 steve Exp $"
#ident "$Id: lexor.lex,v 1.4 1998/11/23 00:20:23 steve Exp $"
#endif
//# define YYSTYPE lexval
@ -48,6 +48,7 @@ static verinum*make_sized_hex(const char*txt);
%x CCOMMENT
%x CSTRING
%s UDPTABLE
%%
@ -81,6 +82,8 @@ static verinum*make_sized_hex(const char*txt);
return STRING; }
<CSTRING>. { yymore(); }
<UDPTABLE>[xXbB01\?] { return yytext[0]; }
[a-zA-Z_][a-zA-Z0-9$_]* {
int rc = check_identifier(yytext);
if (rc == IDENTIFIER)
@ -95,6 +98,8 @@ static verinum*make_sized_hex(const char*txt);
return IDENTIFIER; }
\$([a-zA-Z0-9$_]+) {
if (strcmp(yytext,"$attribute") == 0)
return KK_attribute;
yylval.text = new string(yytext);
return SYSTEM_IDENTIFIER; }
@ -136,6 +141,21 @@ static verinum*make_sized_hex(const char*txt);
%%
/*
* The UDP state table needs some slightly different treatment by the
* lexor. The level characters are normally accepted as other things,
* so the parser needs to switch my mode when it believes in needs to.
*/
void lex_start_table()
{
BEGIN(UDPTABLE);
}
void lex_end_table()
{
BEGIN(INITIAL);
}
static const struct { const char*name; int code; } key_table[] = {
{ "always", K_always },
{ "and", K_and },

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.7 1998/11/18 04:25:22 steve Exp $"
#ident "$Id: netlist.cc,v 1.8 1998/11/23 00:20:23 steve Exp $"
#endif
# include <cassert>
@ -44,6 +44,33 @@ void connect(NetObj::Link&l, NetObj::Link&r)
} while (cur != &l);
}
bool NetObj::Link::is_linked(const NetObj&that) const
{
for (const Link*idx = next_ ; this != idx ; idx = idx->next_)
if (idx->node_ == &that)
return true;
return false;
}
bool NetObj::Link::is_linked(const NetObj::Link&that) const
{
for (const Link*idx = next_ ; this != idx ; idx = idx->next_)
if (idx == &that)
return true;
return false;
}
bool connected(const NetObj&l, const NetObj&r)
{
for (unsigned idx = 0 ; idx < l.pin_count() ; idx += 1)
if (! l.pin(idx).is_linked(r))
return false;
return true;
}
const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx)
{
const NetObj*cur;
@ -77,6 +104,21 @@ NetObj::~NetObj()
delete[]pins_;
}
void NetObj::set_attributes(const map<string,string>&attr)
{
assert(attributes_.size() == 0);
attributes_ = attr;
}
string NetObj::attribute(const string&key) const
{
map<string,string>::const_iterator idx = attributes_.find(key);
if (idx == attributes_.end())
return "";
return (*idx).second;
}
NetNode::~NetNode()
{
if (design_)
@ -94,19 +136,59 @@ NetProc::~NetProc()
}
NetAssign::NetAssign(NetNet*lv, NetExpr*rv)
: NetNode("@assign", lv->pin_count()), lval_(lv), rval_(rv)
: NetNode("@assign", lv->pin_count()), rval_(rv)
{
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
connect(pin(idx), lv->pin(idx));
}
rval_->set_width(lval_->pin_count());
rval_->set_width(lv->pin_count());
}
NetAssign::~NetAssign()
{
}
/*
* This method looks at the objects connected to me, and searches for
* a signal that I am fully connected to. Return that signal, and the
* range of bits that I use.
*/
void NetAssign::find_lval_range(const NetNet*&net, unsigned&msb,
unsigned&lsb) const
{
const NetObj*cur;
unsigned cpin;
for (pin(0).next_link(cur,cpin) ; pin(0) != cur->pin(cpin)
; cur->pin(cpin).next_link(cur, cpin)) {
const NetNet*s = dynamic_cast<const NetNet*>(cur);
if (s == 0)
continue;
if (!connected(*this, *s))
continue;
unsigned idx;
for (idx = 1 ; idx < pin_count() ; idx += 1) {
if (idx+cpin > s->pin_count())
break;
if (! connected(pin(idx), s->pin(idx+cpin)))
break;
}
if (idx < pin_count())
continue;
net = s;
lsb = cpin;
msb = cpin+pin_count()-1;
return;
}
assert(0); // No suitable signals??
}
NetBlock::~NetBlock()
{
}
@ -370,6 +452,14 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/*
* $Log: netlist.cc,v $
* Revision 1.8 1998/11/23 00:20:23 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.7 1998/11/18 04:25:22 steve
* Add -f flags for generic flag key/values.
*

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.7 1998/11/18 04:25:22 steve Exp $"
#ident "$Id: netlist.h,v 1.8 1998/11/23 00:20:23 steve Exp $"
#endif
/*
@ -87,6 +87,15 @@ class NetObj {
// Return true if this link is connected to anything else.
bool is_linked() const { return next_ != this; }
// Return true if these pins are connected.
bool is_linked(const NetObj::Link&that) const;
// Return true if this link is connected to any pin of r.
bool is_linked(const NetObj&r) const;
bool is_equal(const NetObj::Link&that) const
{ return (node_ == that.node_) && (pin_ == that.pin_); }
private:
// The NetNode manages these. They point back to the
// NetNode so that following the links can get me here.
@ -118,6 +127,9 @@ class NetObj {
void delay2(unsigned d) { delay2_ = d; }
void delay3(unsigned d) { delay3_ = d; }
void set_attributes(const map<string,string>&);
string attribute(const string&key) const;
bool test_mark() const { return mark_; }
void set_mark(bool flag=true) { mark_ = flag; }
@ -125,7 +137,7 @@ class NetObj {
const Link&pin(unsigned idx) const { return pins_[idx]; }
void dump_node_pins(ostream&, unsigned) const;
void dump_obj_attr(ostream&, unsigned) const;
private:
string name_;
@ -135,6 +147,8 @@ class NetObj {
unsigned delay2_;
unsigned delay3_;
map<string,string> attributes_;
bool mark_;
};
@ -323,16 +337,17 @@ class NetAssign : public NetProc, public NetNode {
explicit NetAssign(NetNet*lv, NetExpr*rv);
~NetAssign();
const NetNet* lval() const { return lval_; }
const NetExpr*rval() const { return rval_; }
void find_lval_range(const NetNet*&net, unsigned&msb,
unsigned&lsb) const;
virtual void emit_proc(ostream&, struct target_t*) const;
virtual void emit_node(ostream&, struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual void dump_node(ostream&, unsigned ind) const;
private:
NetNet*const lval_;
NetExpr*const rval_;
};
@ -711,11 +726,24 @@ class Design {
/* =======
*/
inline bool operator == (const NetObj::Link&l, const NetObj::Link&r)
{ return l.is_equal(r); }
inline bool operator != (const NetObj::Link&l, const NetObj::Link&r)
{ return ! l.is_equal(r); }
/* Connect the pins of two nodes together. Either may already be
connected to other things, connect is transitive. */
extern void connect(NetObj::Link&, NetObj::Link&);
inline bool connected(const NetObj::Link&l, const NetObj::Link&r)
{ return l.is_linked(r); }
/* Return true if l is fully connected to r. This means, every pin in
l is connected to a pin in r. This is expecially useful for
checking signal vectors. */
extern bool connected(const NetObj&l, const NetObj&r);
/* Find the signal connected to the given node pin. There should
always be exactly one signal. The bidx parameter get filled with
the signal index of the Net, in case it is a vector. */
@ -727,6 +755,14 @@ inline ostream& operator << (ostream&o, const NetExpr&exp)
/*
* $Log: netlist.h,v $
* Revision 1.8 1998/11/23 00:20:23 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.7 1998/11/18 04:25:22 steve
* Add -f flags for generic flag key/values.
*

67
parse.y
View File

@ -19,12 +19,14 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: parse.y,v 1.5 1998/11/11 03:13:04 steve Exp $"
#ident "$Id: parse.y,v 1.6 1998/11/23 00:20:23 steve Exp $"
#endif
# include "parse_misc.h"
# include "pform.h"
extern void lex_start_table();
extern void lex_end_table();
%}
%union {
@ -70,6 +72,8 @@
%token K_trior K_vectored K_wait K_wand K_weak0 K_weak1 K_while K_wire
%token K_wor K_xnor K_xor
%token KK_attribute
%type <text> identifier lvalue register_variable
%type <strings> list_of_register_variables
%type <strings> list_of_variables
@ -138,7 +142,7 @@ delay_opt
description
: module
| primitive
| udp_primitive
;
event_control
@ -433,6 +437,14 @@ module_item
| K_initial statement
{ pform_make_behavior(PProcess::PR_INITIAL, $2);
}
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')' ';'
{ pform_set_attrib(*$3, *$5, *$7);
delete $3;
delete $5;
delete $7;
}
| KK_attribute '(' error ')' ';'
{ yyerror(@1, "Misformed $attribute parameter list."); }
;
module_item_list
@ -480,11 +492,6 @@ port_type
| K_inout { $$ = NetNet::PINOUT; }
;
primitive
: K_primitive IDENTIFIER '(' error ')' ';' K_endprimitive
{ yyerror(@1, "Sorry, primitives not supported."); }
;
range
: '[' const_expression ':' const_expression ']'
{ list<PExpr*>*tmp = new list<PExpr*>;
@ -612,3 +619,49 @@ statement_opt
: statement
| ';' { $$ = 0; }
;
udp_body
: K_table { lex_start_table(); }
udp_comb_entry_list
K_endtable { lex_end_table(); }
;
udp_comb_entry
: udp_input_list ':' udp_output_sym ';'
;
udp_comb_entry_list
: udp_comb_entry
| udp_comb_entry_list udp_comb_entry
;
udp_input_list
: udp_input_sym
| udp_input_list udp_input_sym
;
udp_input_sym : '0' | '1' | 'x' | 'X' | '?' | 'b' | 'B' ;
udp_output_sym : '0' | '1' | 'x' | 'X' ;
udp_port_decl
: K_input list_of_variables ';'
| K_output IDENTIFIER ';'
;
udp_port_decls
: udp_port_decl
| udp_port_decls udp_port_decl
;
udp_port_list
: IDENTIFIER { ; }
| udp_port_list ',' IDENTIFIER { ; }
;
udp_primitive
: K_primitive IDENTIFIER '(' udp_port_list ')' ';'
udp_port_decls
udp_body
K_endprimitive
{ yyerror(@1, "Sorry, UDP primitives not supported."); }
;

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: pform.cc,v 1.3 1998/11/11 00:01:51 steve Exp $"
#ident "$Id: pform.cc,v 1.4 1998/11/23 00:20:23 steve Exp $"
#endif
# include "pform.h"
@ -195,6 +195,13 @@ void pform_set_port_type(const string&name, NetNet::PortType pt)
cur->port_type = pt;
}
void pform_set_attrib(const string&name, const string&key, const string&value)
{
PWire*cur = cur_module->get_wire(name);
assert(cur);
cur->attributes[key] = value;
}
static void pform_set_net_range(const string&name, list<PExpr*>*range)
{
assert(range->size() == 2);
@ -293,6 +300,14 @@ int pform_parse(FILE*input, list<Module*>&modules)
/*
* $Log: pform.cc,v $
* Revision 1.4 1998/11/23 00:20:23 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.3 1998/11/11 00:01:51 steve
* Check net ranges in declarations.
*

12
pform.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: pform.h,v 1.1 1998/11/03 23:29:04 steve Exp $"
#ident "$Id: pform.h,v 1.2 1998/11/23 00:20:23 steve Exp $"
#endif
# include "netlist.h"
@ -85,6 +85,8 @@ extern void pform_makewire(const string&name, NetNet::Type type);
extern void pform_makewire(const list<string>*names, NetNet::Type type);
extern void pform_set_port_type(list<string>*names, NetNet::PortType);
extern void pform_set_net_range(list<string>*names, list<PExpr*>*);
extern void pform_set_attrib(const string&name, const string&key,
const string&value);
extern void pform_make_behavior(PProcess::Type, Statement*);
extern Statement* pform_make_block(PBlock::BL_TYPE, list<Statement*>*);
extern Statement* pform_make_assignment(string*t, PExpr*e);
@ -120,6 +122,14 @@ extern void pform_dump(ostream&out, Module*mod);
/*
* $Log: pform.h,v $
* Revision 1.2 1998/11/23 00:20:23 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.1 1998/11/03 23:29:04 steve
* Introduce verilog to CVS.
*

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.4 1998/11/11 03:13:04 steve Exp $"
#ident "$Id: pform_dump.cc,v 1.5 1998/11/23 00:20:23 steve Exp $"
#endif
/*
@ -130,6 +130,12 @@ void PWire::dump(ostream&out) const
}
out << name << ";" << endl;
for (map<string,string>::const_iterator idx = attributes.begin()
; idx != attributes.end()
; idx ++) {
out << " " << (*idx).first << " = \"" <<
(*idx).second << "\"" << endl;
}
}
void PGate::dump_pins(ostream&out) const
@ -329,6 +335,14 @@ void pform_dump(ostream&out, Module*mod)
/*
* $Log: pform_dump.cc,v $
* Revision 1.5 1998/11/23 00:20:23 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.4 1998/11/11 03:13:04 steve
* Handle while loops.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: t-verilog.cc,v 1.1 1998/11/03 23:29:05 steve Exp $"
#ident "$Id: t-verilog.cc,v 1.2 1998/11/23 00:20:23 steve Exp $"
#endif
/*
@ -117,6 +117,9 @@ void target_verilog::logic(ostream&os, const NetLogic*net)
case NetLogic::OR:
os << " or";
break;
case NetLogic::XNOR:
os << " xnor";
break;
case NetLogic::XOR:
os << " xor";
break;
@ -166,9 +169,22 @@ void target_verilog::proc_assign(ostream&os, const NetAssign*net)
{
os << setw(indent_) << "";
const NetNet*lval = net->lval();
const NetNet*lval;
unsigned msb, lsb;
net->find_lval_range(lval, msb, lsb);
os << mangle(lval->name()) << " = ";
if ((lsb == 0) && (msb == (lval->pin_count()-1))) {
os << mangle(lval->name());
} else if (msb == lsb) {
os << mangle(lval->name()) << "[" << msb << "]";
} else {
os << mangle(lval->name()) << "[" << msb << ":" << lsb <<
"]";
}
os << " = ";
emit_expr_(os, net->rval());
@ -291,6 +307,14 @@ const struct target tgt_verilog = {
/*
* $Log: t-verilog.cc,v $
* Revision 1.2 1998/11/23 00:20:23 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.1 1998/11/03 23:29:05 steve
* Introduce verilog to CVS.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: t-vvm.cc,v 1.5 1998/11/10 00:48:31 steve Exp $"
#ident "$Id: t-vvm.cc,v 1.6 1998/11/23 00:20:23 steve Exp $"
#endif
# include <iostream>
@ -462,14 +462,23 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
{
string rval = emit_proc_rval(os, indent_, net->rval());
os << setw(indent_) << "" << "// " << net->lval()->name() << " = ";
net->rval()->dump(os);
os << endl;
const NetNet*lval;
unsigned msb, lsb;
net->find_lval_range(lval, msb, lsb);
os << setw(indent_) << "" << mangle(net->lval()->name()) << " = "
<< rval << ";" << endl;
if ((lsb == 0) && (msb == (lval->pin_count()-1))) {
os << setw(indent_) << "" << "// " << lval->name()
<< " = ";
net->rval()->dump(os);
os << endl;
os << setw(indent_) << "" << mangle(net->lval()->name()) <<
os << setw(indent_) << "" << mangle(lval->name())
<< " = " << rval << ";" << endl;
} else {
assert(0);
}
os << setw(indent_) << "" << mangle(lval->name()) <<
"_mon.trigger(sim_);" << endl;
@ -479,8 +488,8 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
const NetObj*cur;
unsigned pin;
for (net->lval()->pin(idx).next_link(cur, pin)
; cur != net->lval()
for (net->pin(idx).next_link(cur, pin)
; net->pin(idx) != cur->pin(pin)
; cur->pin(pin).next_link(cur, pin)) {
// Skip NetAssign nodes. They are output-only.
@ -662,6 +671,14 @@ extern const struct target tgt_vvm = {
};
/*
* $Log: t-vvm.cc,v $
* Revision 1.6 1998/11/23 00:20:23 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.5 1998/11/10 00:48:31 steve
* Add support it vvm target for level-sensitive
* triggers (i.e. the Verilog wait).

115
t-xnf.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: t-xnf.cc,v 1.2 1998/11/18 04:25:22 steve Exp $"
#ident "$Id: t-xnf.cc,v 1.3 1998/11/23 00:20:24 steve Exp $"
#endif
/* XNF BACKEND
@ -42,6 +42,7 @@ class target_xnf : public target_t {
public:
void start_design(ostream&os, const Design*);
void end_design(ostream&os, const Design*);
void signal(ostream&os, const NetNet*);
void logic(ostream&os, const NetLogic*);
private:
@ -81,9 +82,90 @@ void target_xnf::end_design(ostream&os, const Design*)
os << "EOF" << endl;
}
void scrape_pad_info(string&str, char&dir, unsigned&num)
{
while (str[0] == ' ')
str = str.substr(1);
switch (str[0]) {
case 'b':
case 'B':
dir = 'B';
break;
case 'o':
case 'O':
dir = 'O';
break;
case 'i':
case 'I':
dir = 'I';
break;
case 't':
case 'T':
dir = 'T';
break;
default:
dir = '?';
break;
}
str = str.substr(1);
unsigned val = 0;
while (str.size() && isdigit(str[0])) {
val = val * 10 + (str[0]-'0');
str = str.substr(1);
}
num = val;
while (str.size() && str[0] == ' ')
str = str.substr(1);
if (str.size() && str[0] == ',')
str = str.substr(1);
}
/*
* Look for signals that have attributes that are pertinent to XNF
* files. The most obvious are those that have the PAD attribute.
*
* Individual signals are easy, the pad description is a letter
* followed by a decimal number that is the pin.
*
* The PAD attribute for a vector is a comma separated pin
* descriptions, that enumerate the pins from most significant to
* least significant.
*/
void target_xnf::signal(ostream&os, const NetNet*net)
{
string pad = net->attribute("PAD");
if (pad != "") {
if (net->pin_count() == 1) {
char dir;
unsigned num;
scrape_pad_info(pad, dir, num);
os << "EXT, " << mangle(net->name()) << ", " << dir
<< ", " << num << endl;
} else for (unsigned idx = net->pin_count(); idx > 0; idx -= 1) {
char dir;
unsigned num;
scrape_pad_info(pad, dir, num);
os << "EXT, " << mangle(net->name()) << "<" << (idx-1)
<< ">, " << dir << ", " << num << endl;
}
}
}
/*
* The logic gates I know so far can be translated directly into XNF
* standard symbol types. This is a fairly obvious transformation.
*/
void target_xnf::logic(ostream&os, const NetLogic*net)
{
os << "SYM," << net->name() << ", ";
os << "SYM, " << mangle(net->name()) << ", ";
switch (net->type()) {
case NetLogic::AND:
os << "AND";
@ -94,6 +176,9 @@ void target_xnf::logic(ostream&os, const NetLogic*net)
case NetLogic::NOR:
os << "NOR";
break;
case NetLogic::NOT:
os << "INV";
break;
case NetLogic::OR:
os << "OR";
break;
@ -104,7 +189,7 @@ void target_xnf::logic(ostream&os, const NetLogic*net)
os << "XOR";
break;
}
os << endl;
os << ", LIBVER=2.0.0" << endl;
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
unsigned cpin;
@ -115,16 +200,20 @@ void target_xnf::logic(ostream&os, const NetLogic*net)
const NetNet*sig = dynamic_cast<const NetNet*>(cur);
if (sig) {
os << "PIN,";
if (idx == 0)
os << "O,O,";
else
os << "I" << idx-1 << ",I,";
os << " PIN, ";
if (idx == 0) {
os << "O, O, ";
} else {
os << "I";
if (net->pin_count() > 2)
os << idx-1;
os << ", I, ";
}
os << mangle(sig->name());
if (sig->pin_count() > 1)
os << "<" << cpin << ">";
os << ",," << endl;
os << endl;
}
}
}
@ -138,6 +227,14 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
/*
* $Log: t-xnf.cc,v $
* Revision 1.3 1998/11/23 00:20:24 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.2 1998/11/18 04:25:22 steve
* Add -f flags for generic flag key/values.
*