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:
Stephen Williams 2010-11-20 15:09:32 -08:00
parent 0c72dfe60f
commit de215f1f8d
29 changed files with 377 additions and 25 deletions

View File

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

View File

@ -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_) << ">";

View File

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

View File

@ -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 << "'"

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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_;

View File

@ -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() << "): "

View File

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

View File

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

42
tgt-stub/enumerate.c Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

49
tgt-vvp/draw_enum.c Normal file
View File

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

View File

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

View File

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

View File

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