Add more support for signed enumerations in SV.
This patch add support for passing if the enumeration is signed or not to the run time. This is really only needed for debug and VPI access.
This commit is contained in:
parent
52019b0e55
commit
609c038484
|
|
@ -22,42 +22,33 @@
|
|||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
# include <inttypes.h>
|
||||
|
||||
// HERE: This still needs work! Fall back to <width>'<signed>b format for
|
||||
// very large constants. This should also be int64_t sized values.
|
||||
// The run time still needs to be modified to work with signed values
|
||||
// and we also need to pass the file and line information.
|
||||
// HERE: This still needs work! Fall back to <width>'b format for
|
||||
// very large constants. We also should pass the file and
|
||||
// line number information for the enum type and the MSB and
|
||||
// LSB should be used instead of the width.
|
||||
/*
|
||||
* If it fits we always print this as a uint64_t the run time will turn
|
||||
* it back into a signed value when needed.
|
||||
*/
|
||||
static void draw_enum2_value(ivl_enumtype_t enumtype, unsigned idx)
|
||||
{
|
||||
long val, mask;
|
||||
uint64_t val, mask;
|
||||
const char*bits = ivl_enum_bits(enumtype, idx);
|
||||
const char*bit;
|
||||
unsigned len = strlen(bits);
|
||||
/* Sign extend if needed. */
|
||||
if (ivl_enum_signed(enumtype)) {
|
||||
assert(len <= sizeof(long)*8);
|
||||
if ((bits[len-1] == '1') && (len < sizeof(long)*8)) {
|
||||
val = -1L & ~((1L << len) - 1L);
|
||||
// HERE: Remove once vvp has been updated.
|
||||
if (ivl_enum_signed(enumtype)) {
|
||||
fprintf(stderr, "%s:%u: tgt-vvp sorry: signed "
|
||||
"enumerations with negative values are not "
|
||||
"currently supported by vvp.\n",
|
||||
ivl_enum_file(enumtype),
|
||||
ivl_enum_lineno(enumtype));
|
||||
vvp_errors += 1;
|
||||
}
|
||||
} else val = 0;
|
||||
} else {
|
||||
assert(len < sizeof(long)*8);
|
||||
val = 0;
|
||||
}
|
||||
|
||||
// HERE: If this doesn't fit then write it as a enum4 and modify the run
|
||||
// time to deal with the conversion.
|
||||
assert(len <= sizeof(uint64_t)*8);
|
||||
val = 0;
|
||||
for (bit = bits, mask = 1 ; *bit != 0 ; bit += 1, mask <<= 1) {
|
||||
if (*bit == '1')
|
||||
val |= mask;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "%ld", val);
|
||||
fprintf(vvp_out, "%" PRIu64, val);
|
||||
}
|
||||
|
||||
static void draw_enum4_value(ivl_enumtype_t enumtype, unsigned idx)
|
||||
|
|
@ -65,8 +56,7 @@ static void draw_enum4_value(ivl_enumtype_t enumtype, unsigned idx)
|
|||
const char*bits = ivl_enum_bits(enumtype, idx);
|
||||
const char*bit;
|
||||
|
||||
fprintf(vvp_out, "%u'%sb", ivl_enum_width(enumtype),
|
||||
ivl_enum_signed(enumtype) ? "s" : "");
|
||||
fprintf(vvp_out, "%u'b", ivl_enum_width(enumtype));
|
||||
|
||||
for (bit = bits+strlen(bits) ; bit > bits ; bit -= 1)
|
||||
fputc(bit[-1], vvp_out);
|
||||
|
|
@ -78,9 +68,10 @@ void draw_enumeration_in_scope(ivl_enumtype_t enumtype)
|
|||
unsigned idx;
|
||||
unsigned name_count = ivl_enum_names(enumtype);
|
||||
const char*dtype = ivl_enum_type(enumtype)==IVL_VT_BOOL? "2" : "4";
|
||||
const char*stype = ivl_enum_signed(enumtype) ? "/s" : "";
|
||||
|
||||
fprintf(vvp_out, "enum%p .enum%s (%u)\n", enumtype,
|
||||
dtype, ivl_enum_width(enumtype));
|
||||
fprintf(vvp_out, "enum%p .enum%s%s (%u)\n", enumtype, dtype, stype,
|
||||
ivl_enum_width(enumtype));
|
||||
|
||||
for (idx = 0 ; idx < name_count ; idx += 1) {
|
||||
fprintf(vvp_out, " \"%s\" ", ivl_enum_name(enumtype, idx));
|
||||
|
|
|
|||
|
|
@ -202,9 +202,9 @@ extern void compile_dff(char*label,
|
|||
struct symb_s arg_e,
|
||||
struct symb_s arg_a);
|
||||
|
||||
extern void compile_enum2_type(char*label, long width,
|
||||
extern void compile_enum2_type(char*label, long width, bool signed_flag,
|
||||
std::list<struct enum_name_s>*names);
|
||||
extern void compile_enum4_type(char*label, long width,
|
||||
extern void compile_enum4_type(char*label, long width, bool signed_flag,
|
||||
std::list<struct enum_name_s>*names);
|
||||
|
||||
class __vpiModPath;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2010-2011 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
|
||||
|
|
@ -40,6 +40,7 @@ static struct enumconst_s* enumconst_from_handle(vpiHandle obj)
|
|||
struct __vpiEnumTypespec {
|
||||
struct __vpiHandle base;
|
||||
std::vector<enumconst_s> names;
|
||||
bool is_signed;
|
||||
};
|
||||
|
||||
static struct __vpiEnumTypespec* vpip_enum_typespec_from_handle(vpiHandle obj)
|
||||
|
|
@ -58,6 +59,10 @@ static int enum_type_get(int code, vpiHandle obj)
|
|||
switch (code) {
|
||||
case vpiSize:
|
||||
return ref->names.size();
|
||||
|
||||
case vpiSigned:
|
||||
return ref->is_signed;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: get %d not supported "
|
||||
"by __vpiEnumTypespec\n", code);
|
||||
|
|
@ -148,11 +153,13 @@ static const struct __vpirt enum_name_rt = {
|
|||
0, //enum_name_put_delays
|
||||
};
|
||||
|
||||
void compile_enum2_type(char*label, long width, std::list<struct enum_name_s>*names)
|
||||
void compile_enum2_type(char*label, long width, bool signed_flag,
|
||||
std::list<struct enum_name_s>*names)
|
||||
{
|
||||
struct __vpiEnumTypespec*spec = new struct __vpiEnumTypespec;
|
||||
spec->base.vpi_type = &enum_type_rt;
|
||||
spec->names = std::vector<enumconst_s> (names->size());
|
||||
spec->is_signed = signed_flag;
|
||||
|
||||
size_t idx = 0;
|
||||
for (list<struct enum_name_s>::iterator cur = names->begin()
|
||||
|
|
@ -170,11 +177,13 @@ void compile_enum2_type(char*label, long width, std::list<struct enum_name_s>*na
|
|||
delete names;
|
||||
}
|
||||
|
||||
void compile_enum4_type(char*label, long width, std::list<struct enum_name_s>*names)
|
||||
void compile_enum4_type(char*label, long width, bool signed_flag,
|
||||
std::list<struct enum_name_s>*names)
|
||||
{
|
||||
struct __vpiEnumTypespec*spec = new struct __vpiEnumTypespec;
|
||||
spec->base.vpi_type = &enum_type_rt;
|
||||
spec->names = std::vector<enumconst_s> (names->size());
|
||||
spec->is_signed = signed_flag;
|
||||
|
||||
size_t idx = 0;
|
||||
for (list<struct enum_name_s>::iterator cur = names->begin()
|
||||
|
|
|
|||
|
|
@ -143,7 +143,9 @@ static char* strdupnew(char const *str)
|
|||
".delay" { return K_DELAY; }
|
||||
".dff" { return K_DFF; }
|
||||
".enum2" { return K_ENUM2; }
|
||||
".enum2/s" { return K_ENUM2_S; }
|
||||
".enum4" { return K_ENUM4; }
|
||||
".enum4/s" { return K_ENUM4_S; }
|
||||
".event" { return K_EVENT; }
|
||||
".event/or" { return K_EVENT_OR; }
|
||||
".export" { return K_EXPORT; }
|
||||
|
|
|
|||
13
vvp/parse.y
13
vvp/parse.y
|
|
@ -80,9 +80,8 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
|
||||
%token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S
|
||||
%token K_CONCAT K_DEBUG K_DELAY K_DFF
|
||||
%token K_ENUM2 K_ENUM4 K_EVENT K_EVENT_OR K_EXPORT K_EXTEND_S K_FUNCTOR
|
||||
%token K_IMPORT K_ISLAND
|
||||
%token K_MODPATH
|
||||
%token K_ENUM2 K_ENUM2_S K_ENUM4 K_ENUM4_S K_EVENT K_EVENT_OR
|
||||
%token K_EXPORT K_EXTEND_S K_FUNCTOR K_IMPORT K_ISLAND K_MODPATH
|
||||
%token K_NET K_NET_S K_NET_R K_NET_2S K_NET_2U K_NET8 K_NET8_S
|
||||
%token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV
|
||||
%token K_PART_V K_PART_V_S K_PORT K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR
|
||||
|
|
@ -810,9 +809,13 @@ statement
|
|||
/* Enumeration types */
|
||||
enum_type
|
||||
: T_LABEL K_ENUM2 '(' T_NUMBER ')' enum_type_names ';'
|
||||
{ compile_enum2_type($1, $4, $6); }
|
||||
{ compile_enum2_type($1, $4, false, $6); }
|
||||
| T_LABEL K_ENUM2_S '(' T_NUMBER ')' enum_type_names ';'
|
||||
{ compile_enum2_type($1, $4, true, $6); }
|
||||
| T_LABEL K_ENUM4 '(' T_NUMBER ')' enum_type_names ';'
|
||||
{ compile_enum4_type($1, $4, $6); }
|
||||
{ compile_enum4_type($1, $4, false, $6); }
|
||||
| T_LABEL K_ENUM4_S '(' T_NUMBER ')' enum_type_names ';'
|
||||
{ compile_enum4_type($1, $4, true, $6); }
|
||||
;
|
||||
|
||||
enum_type_names
|
||||
|
|
|
|||
Loading…
Reference in New Issue