Describe enum type to code generators
This gets the enumeration type through to the ivl_target API so that code generators can do something with it. Generate stub output with tgt-stub, and generate the proper vvp run time to make simple enumerations work from end to end.
This commit is contained in:
parent
0c72dfe60f
commit
de215f1f8d
|
|
@ -200,7 +200,12 @@ extern map<perm_string,bool> library_file_map;
|
|||
* much sense to use a StringHeapLex to hold them.
|
||||
*/
|
||||
extern StringHeapLex lex_strings;
|
||||
extern StringHeap misc_strings;
|
||||
|
||||
/*
|
||||
* The ivl_target.h API in a variety of places keeps strings of
|
||||
* bits. Manage these as perm_string in a StringHeap.
|
||||
*/
|
||||
extern StringHeapLex bits_strings;
|
||||
|
||||
/*
|
||||
* The filename_strings are perm_strings for file names. They are put
|
||||
|
|
|
|||
|
|
@ -1452,6 +1452,11 @@ void NetEEvent::dump(ostream&o) const
|
|||
o << "<event=" << event_->name() << ">";
|
||||
}
|
||||
|
||||
void NetENetenum::dump(ostream&o) const
|
||||
{
|
||||
o << "<netenum=" << netenum_ << ">";
|
||||
}
|
||||
|
||||
void NetEScope::dump(ostream&o) const
|
||||
{
|
||||
o << "<scope=" << scope_path(scope_) << ">";
|
||||
|
|
|
|||
|
|
@ -79,6 +79,12 @@ NetEEvent* NetEEvent::dup_expr() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
NetENetenum* NetENetenum::dup_expr() const
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEScope* NetEScope::dup_expr() const
|
||||
{
|
||||
assert(0);
|
||||
|
|
|
|||
10
elab_expr.cc
10
elab_expr.cc
|
|
@ -2262,11 +2262,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
sys_expr = new NetESFunc("$ivl_method$name", IVL_VT_STRING,0, 1);
|
||||
sys_expr->parm(0, expr);
|
||||
} else if (method_name == "next") {
|
||||
sys_expr = new NetESFunc("$ivl_method$next", netenum, 1);
|
||||
sys_expr->parm(0, expr);
|
||||
sys_expr = new NetESFunc("$ivl_method$next", netenum, 2);
|
||||
sys_expr->parm(0, new NetENetenum(netenum));
|
||||
sys_expr->parm(1, expr);
|
||||
} else if (method_name == "prev") {
|
||||
sys_expr = new NetESFunc("$ivl_method$prev", netenum, 1);
|
||||
sys_expr->parm(0, expr);
|
||||
sys_expr = new NetESFunc("$ivl_method$prev", netenum, 2);
|
||||
sys_expr->parm(0, new NetENetenum(netenum));
|
||||
sys_expr->parm(1, expr);
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Unknown method name `" << method_name << "'"
|
||||
|
|
|
|||
|
|
@ -222,14 +222,16 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
|||
rc_flag = eval_as_long(lsb, lsb_ex);
|
||||
assert(rc_flag);
|
||||
|
||||
netenum_t*use_enum = new netenum_t(enum_type->base_type, enum_type->signed_flag, msb, lsb);
|
||||
netenum_t*use_enum = new netenum_t(enum_type->base_type, enum_type->signed_flag,
|
||||
msb, lsb, enum_type->names->size());
|
||||
|
||||
scope->add_enumeration_set(use_enum);
|
||||
|
||||
verinum cur_value (0);
|
||||
verinum one_value (1);
|
||||
size_t name_idx = 0;
|
||||
for (list<named_pexpr_t>::const_iterator cur = enum_type->names->begin()
|
||||
; cur != enum_type->names->end() ; ++ cur) {
|
||||
; cur != enum_type->names->end() ; ++ cur, name_idx += 1) {
|
||||
|
||||
|
||||
if (cur->parm) {
|
||||
|
|
@ -262,7 +264,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
|||
verinum tmp_val (cur_value, use_enum->base_width());
|
||||
tmp_val.has_sign(enum_type->signed_flag);
|
||||
|
||||
rc_flag = use_enum->insert_name(cur->name, tmp_val);
|
||||
rc_flag = use_enum->insert_name(name_idx, cur->name, tmp_val);
|
||||
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
|
||||
if (! rc_flag) {
|
||||
cerr << "<>:0: error: Duplicate enumeration name " << cur->name << endl;
|
||||
|
|
|
|||
9
emit.cc
9
emit.cc
|
|
@ -385,6 +385,10 @@ void NetScope::emit_scope(struct target_t*tgt) const
|
|||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
|
||||
tgt->event(cur);
|
||||
|
||||
for (list<netenum_t*>::const_iterator cur = enum_sets_.begin()
|
||||
; cur != enum_sets_.end() ; ++cur)
|
||||
tgt->enumeration(this, *cur);
|
||||
|
||||
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
|
||||
; cur != children_.end() ; cur ++)
|
||||
cur->second->emit_scope(tgt);
|
||||
|
|
@ -547,6 +551,11 @@ void NetEEvent::expr_scan(struct expr_scan_t*tgt) const
|
|||
tgt->expr_event(this);
|
||||
}
|
||||
|
||||
void NetENetenum::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_netenum(this);
|
||||
}
|
||||
|
||||
void NetEScope::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_scope(this);
|
||||
|
|
|
|||
20
ivl_target.h
20
ivl_target.h
|
|
@ -159,6 +159,7 @@ typedef struct ivl_branch_s *ivl_branch_t;
|
|||
typedef struct ivl_delaypath_s*ivl_delaypath_t;
|
||||
typedef struct ivl_design_s *ivl_design_t;
|
||||
typedef struct ivl_discipline_s*ivl_discipline_t;
|
||||
typedef struct netenum_t *ivl_enumtype_t;
|
||||
typedef struct ivl_event_s *ivl_event_t;
|
||||
typedef struct ivl_expr_s *ivl_expr_t;
|
||||
typedef struct ivl_island_s *ivl_island_t;
|
||||
|
|
@ -212,6 +213,7 @@ typedef enum ivl_expr_type_e {
|
|||
IVL_EX_BINARY = 2,
|
||||
IVL_EX_CONCAT = 3,
|
||||
IVL_EX_DELAY = 20,
|
||||
IVL_EX_ENUMTYPE = 21,
|
||||
IVL_EX_EVENT = 17,
|
||||
IVL_EX_MEMORY = 4,
|
||||
IVL_EX_NUMBER = 5,
|
||||
|
|
@ -618,6 +620,16 @@ extern ivl_nature_t ivl_discipline_flow(ivl_discipline_t net);
|
|||
|
||||
extern const char* ivl_nature_name(ivl_nature_t net);
|
||||
|
||||
/* ENUMERATIONS
|
||||
*
|
||||
* Enumerations are a collections of symbolic names and vector
|
||||
* values. The enumeration has a base type, and a list of names and
|
||||
* values.
|
||||
*/
|
||||
extern unsigned ivl_enum_names(ivl_enumtype_t net);
|
||||
extern const char*ivl_enum_name(ivl_enumtype_t net, unsigned idx);
|
||||
extern const char*ivl_enum_bits(ivl_enumtype_t net, unsigned idx);
|
||||
|
||||
/* EVENTS
|
||||
*
|
||||
* Events are a unification of named events and implicit events
|
||||
|
|
@ -774,6 +786,8 @@ extern ivl_scope_t ivl_expr_def(ivl_expr_t net);
|
|||
extern uint64_t ivl_expr_delay_val(ivl_expr_t net);
|
||||
/* IVL_EX_REALNUM */
|
||||
extern double ivl_expr_dvalue(ivl_expr_t net);
|
||||
/* IVL_EX_ENUMTYPE */
|
||||
extern ivl_enumtype_t ivl_expr_enumtype(ivl_expr_t net);
|
||||
/* IVL_EX_SIGNAL, IVL_EX_SFUNC, IVL_EX_VARIABLE */
|
||||
extern const char* ivl_expr_name(ivl_expr_t net);
|
||||
/* IVL_EX_BACCESS */
|
||||
|
|
@ -1550,6 +1564,10 @@ extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
|||
* ivl_scope_def_lineno
|
||||
* Returns the file and line where this scope is defined.
|
||||
*
|
||||
* ivl_scope_enumerate
|
||||
* ivl_scope_enumerates
|
||||
* Scopes have 0 or more enumeration types in them.
|
||||
*
|
||||
* ivl_scope_event
|
||||
* ivl_scope_events
|
||||
* Scopes have 0 or more event objects in them.
|
||||
|
|
@ -1637,6 +1655,8 @@ extern ivl_statement_t ivl_scope_def(ivl_scope_t net);
|
|||
extern const char* ivl_scope_def_file(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_def_lineno(ivl_scope_t net);
|
||||
|
||||
extern unsigned ivl_scope_enumerates(ivl_scope_t net);
|
||||
extern ivl_enumtype_t ivl_scope_enumerate(ivl_scope_t net, unsigned idx);
|
||||
extern unsigned ivl_scope_events(ivl_scope_t net);
|
||||
extern ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx);
|
||||
extern const char* ivl_scope_file(ivl_scope_t net);
|
||||
|
|
|
|||
3
main.cc
3
main.cc
|
|
@ -176,6 +176,8 @@ StringHeapLex lex_strings;
|
|||
|
||||
StringHeapLex filename_strings;
|
||||
|
||||
StringHeapLex bits_strings;
|
||||
|
||||
/*
|
||||
* In library searches, Windows file names are never case sensitive.
|
||||
*/
|
||||
|
|
@ -748,6 +750,7 @@ static void EOC_cleanup(void)
|
|||
flags.clear();
|
||||
|
||||
lex_strings.cleanup();
|
||||
bits_strings.cleanup();
|
||||
filename_strings.cleanup();
|
||||
}
|
||||
|
||||
|
|
|
|||
15
net_expr.cc
15
net_expr.cc
|
|
@ -506,6 +506,21 @@ const NetScope* NetECRealParam::scope() const
|
|||
}
|
||||
|
||||
|
||||
NetENetenum::NetENetenum(netenum_t*s)
|
||||
: netenum_(s)
|
||||
{
|
||||
}
|
||||
|
||||
NetENetenum::~NetENetenum()
|
||||
{
|
||||
}
|
||||
|
||||
netenum_t* NetENetenum::netenum() const
|
||||
{
|
||||
return netenum_;
|
||||
}
|
||||
|
||||
|
||||
NetEParam::NetEParam()
|
||||
: des_(0), scope_(0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -100,6 +100,11 @@ NexusSet* NetEEvent::nex_input(bool rem_out)
|
|||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetENetenum::nex_input(bool rem_out)
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetEScope::nex_input(bool rem_out)
|
||||
{
|
||||
return new NexusSet;
|
||||
|
|
|
|||
53
netenum.cc
53
netenum.cc
|
|
@ -18,10 +18,13 @@
|
|||
*/
|
||||
|
||||
# include "netenum.h"
|
||||
# include "compiler.h"
|
||||
# include <cassert>
|
||||
|
||||
netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag, long msb, long lsb)
|
||||
: base_type_(btype), signed_flag_(signed_flag), msb_(msb), lsb_(lsb)
|
||||
netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag,
|
||||
long msb, long lsb, size_t name_count)
|
||||
: base_type_(btype), signed_flag_(signed_flag), msb_(msb), lsb_(lsb),
|
||||
names_(name_count), bits_(name_count)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -29,15 +32,19 @@ netenum_t::~netenum_t()
|
|||
{
|
||||
}
|
||||
|
||||
bool netenum_t::insert_name(perm_string name, const verinum&val)
|
||||
bool netenum_t::insert_name(size_t name_idx, perm_string name, const verinum&val)
|
||||
{
|
||||
std::pair<std::map<perm_string,verinum>::iterator, bool> res;
|
||||
|
||||
assert(val.has_len() && val.len() == (msb_-lsb_+1));
|
||||
|
||||
// Insert a map of the name to the value. This also gets a
|
||||
// flag that returns true if the name is unique, or false
|
||||
// otherwise.
|
||||
res = names_map_.insert( make_pair(name,val) );
|
||||
// Only add the name to the list if it is not there already.
|
||||
if (res.second) names_.push_back(name);
|
||||
|
||||
assert(name_idx < names_.size() && names_[name_idx] == 0);
|
||||
names_[name_idx] = name;
|
||||
|
||||
return res.second;
|
||||
}
|
||||
|
|
@ -61,3 +68,39 @@ netenum_t::iterator netenum_t::last_name() const
|
|||
{
|
||||
return names_map_.find(names_.back());
|
||||
}
|
||||
|
||||
perm_string netenum_t::name_at(size_t idx) const
|
||||
{
|
||||
assert(idx < names_.size());
|
||||
return names_[idx];
|
||||
}
|
||||
|
||||
perm_string netenum_t::bits_at(size_t idx)
|
||||
{
|
||||
assert(idx < names_.size());
|
||||
|
||||
if (bits_[idx] == 0) {
|
||||
netenum_t::iterator cur = names_map_.find(names_[idx]);
|
||||
|
||||
vector<char>str (cur->second.len() + 1);
|
||||
for (unsigned bit = 0 ; bit < cur->second.len() ; bit += 1) {
|
||||
switch (cur->second.get(bit)) {
|
||||
case verinum::V0:
|
||||
str[bit] = '0';
|
||||
break;
|
||||
case verinum::V1:
|
||||
str[bit] = '1';
|
||||
break;
|
||||
case verinum::Vx:
|
||||
str[bit] = 'x';
|
||||
break;
|
||||
case verinum::Vz:
|
||||
str[bit] = 'z';
|
||||
break;
|
||||
}
|
||||
}
|
||||
bits_[idx] = bits_strings.make(&str[0]);
|
||||
}
|
||||
|
||||
return bits_[idx];
|
||||
}
|
||||
|
|
|
|||
17
netenum.h
17
netenum.h
|
|
@ -22,14 +22,16 @@
|
|||
# include "ivl_target.h"
|
||||
# include "verinum.h"
|
||||
# include "StringHeap.h"
|
||||
# include <list>
|
||||
# include <vector>
|
||||
# include <map>
|
||||
|
||||
class NetScope;
|
||||
|
||||
class netenum_t {
|
||||
|
||||
public:
|
||||
explicit netenum_t(ivl_variable_type_t base_type, bool signed_flag,
|
||||
long msb, long lsb);
|
||||
long msb, long lsb, size_t name_count);
|
||||
~netenum_t();
|
||||
|
||||
ivl_variable_type_t base_type() const;
|
||||
|
|
@ -38,7 +40,10 @@ class netenum_t {
|
|||
// The size() is the number of enumeration literals.
|
||||
size_t size() const;
|
||||
|
||||
bool insert_name(perm_string name, const verinum&val);
|
||||
// Insert the name (and value) at the specific place in the
|
||||
// enumeration. This must be done exactly once for each
|
||||
// enumeration value.
|
||||
bool insert_name(size_t idx, perm_string name, const verinum&val);
|
||||
|
||||
typedef std::map<perm_string,verinum>::const_iterator iterator;
|
||||
iterator find_name(perm_string name) const;
|
||||
|
|
@ -48,13 +53,17 @@ class netenum_t {
|
|||
iterator first_name() const;
|
||||
iterator last_name() const;
|
||||
|
||||
perm_string name_at(size_t idx) const;
|
||||
perm_string bits_at(size_t idx);
|
||||
|
||||
private:
|
||||
ivl_variable_type_t base_type_;
|
||||
bool signed_flag_;
|
||||
long msb_, lsb_;
|
||||
|
||||
std::map<perm_string,verinum> names_map_;
|
||||
std::list<perm_string> names_;
|
||||
std::vector<perm_string> names_;
|
||||
std::vector<perm_string> bits_;
|
||||
};
|
||||
|
||||
inline ivl_variable_type_t netenum_t::base_type() const
|
||||
|
|
|
|||
23
netlist.h
23
netlist.h
|
|
@ -3715,6 +3715,29 @@ class NetEEvent : public NetExpr {
|
|||
NetEvent*event_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class is a special (and magical) expression node type that
|
||||
* represents enumeration types. These can only be found as parameters
|
||||
* to NetSTask objects.
|
||||
*/
|
||||
class NetENetenum : public NetExpr {
|
||||
|
||||
public:
|
||||
NetENetenum(netenum_t*);
|
||||
~NetENetenum();
|
||||
|
||||
netenum_t* netenum() const;
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetENetenum* dup_expr() const;
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
virtual void dump(ostream&os) const;
|
||||
|
||||
private:
|
||||
netenum_t*netenum_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class is a special (and magical) expression node type that
|
||||
* represents scope names. These can only be found as parameters to
|
||||
|
|
|
|||
40
t-dll-api.cc
40
t-dll-api.cc
|
|
@ -21,6 +21,7 @@
|
|||
# include "StringHeap.h"
|
||||
# include "t-dll.h"
|
||||
# include "discipline.h"
|
||||
# include "netenum.h"
|
||||
# include "ivl_alloc.h"
|
||||
# include <cstdlib>
|
||||
# include <cstdio>
|
||||
|
|
@ -210,6 +211,26 @@ extern "C" unsigned ivl_const_width(ivl_net_const_t net)
|
|||
return net->width_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_enum_names(ivl_enumtype_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->size();
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_enum_name(ivl_enumtype_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->size());
|
||||
return net->name_at(idx);
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_enum_bits(ivl_enumtype_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->size());
|
||||
return net->bits_at(idx);
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_event_name(ivl_event_t net)
|
||||
{
|
||||
static char*name_buffer = 0;
|
||||
|
|
@ -323,6 +344,12 @@ extern "C" double ivl_expr_dvalue(ivl_expr_t net)
|
|||
return net->u_.real_.value;
|
||||
}
|
||||
|
||||
extern "C" ivl_enumtype_t ivl_expr_enumtype(ivl_expr_t net)
|
||||
{
|
||||
assert(net->type_ == IVL_EX_ENUMTYPE);
|
||||
return net->u_.enumtype_.type;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_expr_name(ivl_expr_t net)
|
||||
{
|
||||
switch (net->type_) {
|
||||
|
|
@ -1671,6 +1698,19 @@ extern "C" unsigned ivl_scope_def_lineno(ivl_scope_t net)
|
|||
return net->def_lineno;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_scope_enumerates(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->enumerations_.size();
|
||||
}
|
||||
|
||||
extern "C" ivl_enumtype_t ivl_scope_enumerate(ivl_scope_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->enumerations_.size());
|
||||
return net->enumerations_[idx];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_scope_events(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
|
|
|
|||
|
|
@ -340,6 +340,17 @@ void dll_target::expr_scope(const NetEScope*net)
|
|||
expr_->u_.scope_.scope = lookup_scope_(net->scope());
|
||||
}
|
||||
|
||||
void dll_target::expr_netenum(const NetENetenum*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
|
||||
expr_->type_ = IVL_EX_ENUMTYPE;
|
||||
expr_->value_= IVL_VT_VOID;
|
||||
expr_->u_.enumtype_.type = net->netenum();
|
||||
}
|
||||
|
||||
void dll_target::expr_select(const NetESelect*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
|
|
|
|||
12
t-dll.cc
12
t-dll.cc
|
|
@ -396,6 +396,11 @@ void scope_add_logic(ivl_scope_t scope, ivl_net_logic_t net)
|
|||
|
||||
}
|
||||
|
||||
static void scope_add_enumeration(ivl_scope_t scope, ivl_enumtype_t net)
|
||||
{
|
||||
scope->enumerations_.push_back(net);
|
||||
}
|
||||
|
||||
void scope_add_event(ivl_scope_t scope, ivl_event_t net)
|
||||
{
|
||||
if (scope->nevent_ == 0) {
|
||||
|
|
@ -786,6 +791,13 @@ bool dll_target::bufz(const NetBUFZ*net)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool dll_target::enumeration(const NetScope*in_scope, netenum_t*net)
|
||||
{
|
||||
ivl_scope_t scop = find_scope(des_, in_scope);
|
||||
scope_add_enumeration(scop, net);
|
||||
return true;
|
||||
}
|
||||
|
||||
void dll_target::event(const NetEvent*net)
|
||||
{
|
||||
struct ivl_event_s *obj = new struct ivl_event_s;
|
||||
|
|
|
|||
8
t-dll.h
8
t-dll.h
|
|
@ -58,6 +58,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
|
||||
bool bufz(const NetBUFZ*);
|
||||
bool branch(const NetBranch*);
|
||||
bool enumeration(const NetScope*, netenum_t*);
|
||||
void event(const NetEvent*);
|
||||
void logic(const NetLogic*);
|
||||
bool tran(const NetTran*);
|
||||
|
|
@ -139,6 +140,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void expr_rparam(const NetECRealParam*);
|
||||
void expr_event(const NetEEvent*);
|
||||
void expr_scope(const NetEScope*);
|
||||
void expr_netenum(const NetENetenum*);
|
||||
void expr_select(const NetESelect*);
|
||||
void expr_sfunc(const NetESFunc*);
|
||||
void expr_ternary(const NetETernary*);
|
||||
|
|
@ -251,6 +253,10 @@ struct ivl_expr_s {
|
|||
ivl_scope_t scope;
|
||||
} scope_;
|
||||
|
||||
struct {
|
||||
ivl_enumtype_t type;
|
||||
} enumtype_;
|
||||
|
||||
struct {
|
||||
ivl_signal_t sig;
|
||||
ivl_expr_t word;
|
||||
|
|
@ -599,6 +605,8 @@ struct ivl_scope_s {
|
|||
unsigned def_lineno;
|
||||
ivl_scope_type_t type_;
|
||||
|
||||
std::vector<ivl_enumtype_t> enumerations_;
|
||||
|
||||
unsigned nsigs_;
|
||||
ivl_signal_t*sigs_;
|
||||
|
||||
|
|
|
|||
13
target.cc
13
target.cc
|
|
@ -45,6 +45,13 @@ void target_t::event(const NetEvent*ev)
|
|||
<< "): Unhandled event <" << ev->name() << ">." << endl;
|
||||
}
|
||||
|
||||
bool target_t::enumeration(const NetScope*, netenum_t*obj)
|
||||
{
|
||||
cerr << "<>:0" << ": error: target (" << typeid(*this).name()
|
||||
<< "): Unhandled enumeration <" << obj << ">." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::signal_paths(const NetNet*)
|
||||
{
|
||||
return true;
|
||||
|
|
@ -460,6 +467,12 @@ void expr_scan_t::expr_event(const NetEEvent*)
|
|||
"unhandled expr_event." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_netenum(const NetENetenum*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
"unhandled expr_netenum." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_scope(const NetEScope*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
|
|
|
|||
4
target.h
4
target.h
|
|
@ -59,6 +59,9 @@ struct target_t {
|
|||
/* Output an event object. Called for each named event in the scope. */
|
||||
virtual void event(const NetEvent*);
|
||||
|
||||
/* Output an enumeration typespec. */
|
||||
virtual bool enumeration(const NetScope*, netenum_t*);
|
||||
|
||||
/* Output a signal (called for each signal) */
|
||||
virtual void signal(const NetNet*) =0;
|
||||
virtual bool signal_paths(const NetNet*);
|
||||
|
|
@ -156,6 +159,7 @@ struct expr_scan_t {
|
|||
virtual void expr_ufunc(const NetEUFunc*);
|
||||
virtual void expr_unary(const NetEUnary*);
|
||||
virtual void expr_binary(const NetEBinary*);
|
||||
virtual void expr_netenum(const NetENetenum*);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
|
|||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = stub.o expression.o statement.o switches.o
|
||||
O = stub.o enumerate.o expression.o statement.o switches.o
|
||||
|
||||
all: dep stub.tgt
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "priv.h"
|
||||
# include <string.h>
|
||||
|
||||
void show_enumerate(ivl_enumtype_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
fprintf(out, " enumeration %p {\n", net);
|
||||
|
||||
for (idx = 0 ; idx < ivl_enum_names(net) ; idx += 1) {
|
||||
fprintf(out, " %s = <", ivl_enum_name(net, idx));
|
||||
|
||||
const char*bits = ivl_enum_bits(net, idx);
|
||||
size_t bits_len = strlen(bits);
|
||||
size_t bit;
|
||||
for (bit = bits_len ; bit > 0 ; bit -= 1)
|
||||
fputc(bits[bit-1], out);
|
||||
|
||||
fprintf(out, ">\n");
|
||||
}
|
||||
|
||||
fprintf(out, " }\n");
|
||||
}
|
||||
|
|
@ -137,6 +137,11 @@ static void show_binary_expression(ivl_expr_t net, unsigned ind)
|
|||
}
|
||||
}
|
||||
|
||||
static void show_enumtype_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
fprintf(out, "%*s<enumtype=%p>\n", ind, "", ivl_expr_enumtype(net));
|
||||
}
|
||||
|
||||
static void show_function_call(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
ivl_scope_t def = ivl_expr_def(net);
|
||||
|
|
@ -282,6 +287,10 @@ void show_expression(ivl_expr_t net, unsigned ind)
|
|||
|
||||
break;
|
||||
|
||||
case IVL_EX_ENUMTYPE:
|
||||
show_enumtype_expression(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_MEMORY:
|
||||
show_memory_expression(net, ind);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ extern ivl_discipline_t discipline_of_nexus(ivl_nexus_t nex);
|
|||
*/
|
||||
extern void test_expr_is_delay(ivl_expr_t expr);
|
||||
|
||||
extern void show_enumerate(ivl_enumtype_t net);
|
||||
|
||||
/*
|
||||
* Show the details of the expression.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1590,6 +1590,9 @@ static int show_scope(ivl_scope_t net, void*x)
|
|||
for (idx = 0 ; idx < ivl_scope_params(net) ; idx += 1)
|
||||
show_parameter(ivl_scope_param(net, idx));
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_enumerates(net) ; idx += 1)
|
||||
show_enumerate(ivl_scope_enumerate(net, idx));
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1)
|
||||
show_signal(ivl_scope_sig(net, idx));
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
|
|||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = vvp.o draw_mux.o draw_net_input.o draw_switch.o draw_ufunc.o draw_vpi.o \
|
||||
O = vvp.o draw_enum.o draw_mux.o draw_net_input.o draw_switch.o draw_ufunc.o draw_vpi.o \
|
||||
eval_bool.o eval_expr.o eval_real.o modpath.o vector.o vvp_process.o \
|
||||
vvp_scope.o
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "vvp_priv.h"
|
||||
# include "ivl_alloc.h"
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
void draw_enumeration_in_scope(ivl_enumtype_t enumtype)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
fprintf(vvp_out, "enum%p .enum\n", enumtype);
|
||||
|
||||
for (idx = 0 ; idx < ivl_enum_names(enumtype) ; idx += 1) {
|
||||
const char*comma = idx+1 < ivl_enum_names(enumtype)? "," : "";
|
||||
|
||||
fprintf(vvp_out, " \"%s\"", ivl_enum_name(enumtype, idx));
|
||||
|
||||
long val = 0;
|
||||
long mask = 1;
|
||||
const char*bits = ivl_enum_bits(enumtype, idx);
|
||||
const char*bit;
|
||||
for (bit = bits, mask = 1 ; bit[0] != 0 ; bit += 1, mask <<= 1) {
|
||||
if (*bit == '1')
|
||||
val |= mask;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %ld%s\n", val, comma);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " ;\n");
|
||||
}
|
||||
|
|
@ -287,7 +287,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
assert((unsigned)(dp - buffer) <= sizeof buffer);
|
||||
}
|
||||
args[idx].text = strdup(buffer);
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
case IVL_EX_STRING:
|
||||
|
|
@ -308,6 +308,10 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
}
|
||||
break;
|
||||
|
||||
case IVL_EX_ENUMTYPE:
|
||||
snprintf(buffer, sizeof buffer, "enum%p", ivl_expr_enumtype(expr));
|
||||
args[idx].text = strdup(buffer);
|
||||
continue;
|
||||
case IVL_EX_EVENT:
|
||||
snprintf(buffer, sizeof buffer, "E_%p", ivl_expr_event(expr));
|
||||
args[idx].text = strdup(buffer);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@
|
|||
# include "ivl_target.h"
|
||||
# include <stdio.h>
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The target_design entry opens the output file that receives the
|
||||
* compiled design, and sets the vvp_out to the descriptor.
|
||||
|
|
|
|||
|
|
@ -25,11 +25,6 @@
|
|||
# include <inttypes.h>
|
||||
# include <assert.h>
|
||||
|
||||
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Escape non-symbol characters in ids, and quotes in strings.
|
||||
*/
|
||||
|
|
@ -2026,6 +2021,14 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
|||
}
|
||||
}
|
||||
|
||||
/* Scan the scope for enumeration types, and write out
|
||||
enumeration typespecs. */
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_enumerates(net) ; idx += 1) {
|
||||
ivl_enumtype_t enumtype = ivl_scope_enumerate(net, idx);
|
||||
draw_enumeration_in_scope(enumtype);
|
||||
}
|
||||
|
||||
/* Scan the scope for logic devices. For each device, draw out
|
||||
a functor that connects pin 0 to the output, and the
|
||||
remaining pins to inputs. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue