Merge branch 'master' into work7

This commit is contained in:
Stephen Williams 2011-07-24 11:06:22 -07:00
commit 116d9f5f54
25 changed files with 803 additions and 161 deletions

View File

@ -152,6 +152,21 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
verinum cur_value (0);
verinum one_value (1);
size_t name_idx = 0;
// Find the minimum and maximum allowed enumeration values.
verinum min_value (0);
verinum max_value (0);
if (enum_type->signed_flag) {
min_value = v_not((pow(verinum(2),
verinum(use_enum->base_width()-1)))) +
one_value;
max_value = pow(verinum(2), verinum(use_enum->base_width()-1)) -
one_value;
} else {
max_value = pow(verinum(2), verinum(use_enum->base_width())) -
one_value;
}
min_value.has_sign(true);
max_value.has_sign(enum_type->signed_flag);
for (list<named_pexpr_t>::const_iterator cur = enum_type->names->begin()
; cur != enum_type->names->end() ; ++ cur, name_idx += 1) {
@ -159,38 +174,60 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
if (cur->parm) {
// There is an explicit value. elaborate/evaluate
// the value and assign it to the enumeration name.
NetExpr*val = elab_and_eval(des, scope, cur->parm,
use_enum->base_width());
NetExpr*val = elab_and_eval(des, scope, cur->parm, -1);
NetEConst*val_const = dynamic_cast<NetEConst*> (val);
if (val_const == 0) {
cerr << "<>:0: error: Enumeration expression is not constant." << endl;
cerr << "<>:0: error: Enumeration expression is not "
"constant." << endl;
des->errors += 1;
continue;
}
cur_value = val_const->value();
if (enum_type->base_type==IVL_VT_BOOL && ! cur_value.is_defined()) {
if (enum_type->base_type==IVL_VT_BOOL &&
! cur_value.is_defined()) {
cerr << "<>:0: error: Enumeration name " << cur->name
<< " cannot have a logic value." << endl;
<< " cannot have an undefined value." << endl;
des->errors += 1;
continue;
}
} else if (! cur_value.is_defined()) {
cerr << "<>:0: error: Enumeration name " << cur->name
<< " cannot have an inferred value." << endl;
<< " cannot have an undefined inferred value." << endl;
des->errors += 1;
continue;
}
// The enumeration value must fit into the enumeration bits.
if ((cur_value > max_value) ||
(cur_value.has_sign() && (cur_value < min_value))) {
cerr << "<>:0: error: Enumeration name " << cur->name
<< " cannot have a value equal to " << cur_value
<< "." << endl;
des->errors += 1;
}
// The values are explicitly sized to the width of the
// base type of the enumeration.
verinum tmp_val (cur_value, use_enum->base_width());
verinum tmp_val (0);
if (cur_value.len() < use_enum->base_width()) {
// Pad the current value if it is narrower than the final
// width of the enum.
tmp_val = pad_to_width (cur_value, use_enum->base_width());
tmp_val.has_len(true);
} else {
// Truncate an oversized value. We report out of bound
// values above. This may create duplicates.
tmp_val = verinum(cur_value, use_enum->base_width());
}
tmp_val.has_sign(enum_type->signed_flag);
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;
cerr << "<>:0: error: Duplicate enumeration name "
<< cur->name << endl;
des->errors += 1;
}

View File

@ -145,6 +145,20 @@ TU [munpf]
"<=" { return K_LE; }
">=" { return K_GE; }
"=>" { return K_EG; }
"+=>"|"-=>" {
/*
* Resolve the ambiguity between the += assignment
* operator and +=> polarity edge path operator
*
* +=> should be treated as two separate tokens '+' and
* '=>' (K_EG), therefore we only consume the first
* character of the matched pattern i.e. either + or -
* and push back the rest of the matches text (=>) in
* the input stream.
*/
yyless(1);
return yytext[0];
}
"*>" { return K_SG; }
"==" { return K_EQ; }
"!=" { return K_NE; }
@ -161,6 +175,19 @@ TU [munpf]
"+:" { return K_PO_POS; }
"-:" { return K_PO_NEG; }
"<+" { return K_CONTRIBUTE; }
"+=" { return K_PLUS_EQ; }
"-=" { return K_MINUS_EQ; }
"*=" { return K_MUL_EQ; }
"/=" { return K_DIV_EQ; }
"%=" { return K_MOD_EQ; }
"&=" { return K_AND_EQ; }
"|=" { return K_OR_EQ; }
"^=" { return K_XOR_EQ; }
"<<=" { return K_LS_EQ; }
">>=" { return K_RS_EQ; }
"<<<=" { return K_LS_EQ; }
">>>=" { return K_RSS_EQ; }
/* Watch out for the tricky case of (*). Cannot parse this as "(*"
and ")", but since I know that this is really ( * ), replace it

View File

@ -184,7 +184,15 @@ NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
NetExpr* cast_to_int2(NetExpr*expr)
{
NetECast*cast = new NetECast('2', expr, expr->expr_width(),
// Special case: The expression is alreadt BOOL
if (expr->expr_type() == IVL_VT_BOOL)
return expr;
unsigned use_width = expr->expr_width();
if (expr->expr_type() == IVL_VT_REAL)
use_width = 64;
NetECast*cast = new NetECast('2', expr, use_width,
expr->has_sign());
cast->set_line(*expr);
return cast;

194
parse.y
View File

@ -197,14 +197,26 @@ static list<named_pexpr_t>* make_named_numbers(perm_string name, long first, lon
{
list<named_pexpr_t>*lst = new list<named_pexpr_t>;
named_pexpr_t tmp;
assert(first <= last);
for (long idx = first ; idx <= last ; idx += 1) {
ostringstream buf;
buf << name.str() << idx << ends;
tmp.name = lex_strings.make(buf.str());
tmp.parm = val;
val = 0;
lst->push_back(tmp);
// We are counting up.
if (first <= last) {
for (long idx = first ; idx <= last ; idx += 1) {
ostringstream buf;
buf << name.str() << idx << ends;
tmp.name = lex_strings.make(buf.str());
tmp.parm = val;
val = 0;
lst->push_back(tmp);
}
// We are counting down.
} else {
for (long idx = first ; idx >= last ; idx -= 1) {
ostringstream buf;
buf << name.str() << idx << ends;
tmp.name = lex_strings.make(buf.str());
tmp.parm = val;
val = 0;
lst->push_back(tmp);
}
}
return lst;
}
@ -219,6 +231,28 @@ static list<named_pexpr_t>* make_named_number(perm_string name, PExpr*val =0)
return lst;
}
static long check_enum_seq_value(const YYLTYPE&loc, verinum *arg, bool zero_ok)
{
long value = 1;
// We can never have an undefined value in an enumeration name
// declaration sequence.
if (! arg->is_defined()) {
yyerror(loc, "error: undefined value used in enum name sequence.");
// We can never have a negative value in an enumeration name
// declaration sequence.
} else if (arg->is_negative()) {
yyerror(loc, "error: negative value used in enum name sequence.");
} else {
value = arg->as_ulong();
// We cannot have a zero enumeration name declaration count.
if (! zero_ok && (value == 0)) {
yyerror(loc, "error: zero count used in enum name sequence.");
value = 1;
}
}
return value;
}
%}
%union {
@ -296,6 +330,7 @@ static list<named_pexpr_t>* make_named_number(perm_string name, PExpr*val =0)
%token <text> PATHPULSE_IDENTIFIER
%token <number> BASED_NUMBER DEC_NUMBER
%token <realtime> REALTIME
%token K_PLUS_EQ K_MINUS_EQ
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_RSS K_SG
/* K_CONTRIBUTE is <+, the contribution assign. */
%token K_CONTRIBUTE
@ -387,7 +422,7 @@ static list<named_pexpr_t>* make_named_number(perm_string name, PExpr*val =0)
%token K_zi_nd K_zi_np K_zi_zd K_zi_zp
%type <flag> from_exclude
%type <number> number
%type <number> number pos_neg_number
%type <flag> unsigned_signed_opt signed_unsigned_opt reg_opt
%type <flag> udp_reg_opt edge_operator automatic_opt
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
@ -455,7 +490,7 @@ static list<named_pexpr_t>* make_named_number(perm_string name, PExpr*val =0)
%type <event_expr> event_expression_list
%type <event_expr> event_expression
%type <event_statement> event_control
%type <statement> statement statement_or_null
%type <statement> statement statement_or_null compressed_statement
%type <statement_list> statement_list
%type <statement> analog_statement
@ -469,6 +504,8 @@ static list<named_pexpr_t>* make_named_number(perm_string name, PExpr*val =0)
%type <int_val> atom2_type
%token K_TAND
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
%right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
%right '?' ':'
%left K_LOR
%left K_LAND
@ -774,22 +811,34 @@ enum_name_list
}
;
pos_neg_number
: number
{ $$ = $1;
}
| '-' number
{ verinum tmp = v_not(*($2)) + verinum(1);
*($2) = tmp;
$$ = $2;
}
;
enum_name
: IDENTIFIER
{ perm_string name = lex_strings.make($1);
delete[]$1;
$$ = make_named_number(name);
}
| IDENTIFIER '[' DEC_NUMBER ']'
| IDENTIFIER '[' pos_neg_number ']'
{ perm_string name = lex_strings.make($1);
long count = $3->as_ulong();
long count = check_enum_seq_value(@1, $3, false);
delete[]$1;
$$ = make_named_numbers(name, 0, count-1);
delete $3;
}
| IDENTIFIER '[' DEC_NUMBER ':' DEC_NUMBER ']'
| IDENTIFIER '[' pos_neg_number ':' pos_neg_number ']'
{ perm_string name = lex_strings.make($1);
$$ = make_named_numbers(name, $3->as_long(), $5->as_long());
$$ = make_named_numbers(name, check_enum_seq_value(@1, $3, true),
check_enum_seq_value(@1, $5, true));
delete[]$1;
delete $3;
delete $5;
@ -799,16 +848,17 @@ enum_name
delete[]$1;
$$ = make_named_number(name, $3);
}
| IDENTIFIER '[' DEC_NUMBER ']' '=' expression
| IDENTIFIER '[' pos_neg_number ']' '=' expression
{ perm_string name = lex_strings.make($1);
long count = $3->as_ulong();
long count = check_enum_seq_value(@1, $3, false);
$$ = make_named_numbers(name, 0, count-1, $6);
delete[]$1;
delete $3;
}
| IDENTIFIER '[' DEC_NUMBER ':' DEC_NUMBER ']' '=' expression
| IDENTIFIER '[' pos_neg_number ':' pos_neg_number ']' '=' expression
{ perm_string name = lex_strings.make($1);
$$ = make_named_numbers(name, $3->as_long(), $5->as_long(), $8);
$$ = make_named_numbers(name, check_enum_seq_value(@1, $3, true),
check_enum_seq_value(@1, $5, true), $8);
delete[]$1;
delete $3;
delete $5;
@ -976,21 +1026,21 @@ delay_value_simple
delete[]$1;
}
| TIME_LITERAL
{
int unit;
{ int unit;
based_size = 0;
$$ = 0;
if ($1 == 0 || !get_time_unit($1, unit))
yyerror(@1, "internal error: delay.");
else {
double p = pow(10, unit - pform_get_timeunit());
double time = atof($1) * p;
based_size = 0;
$$ = 0;
if ($1 == 0 || !get_time_unit($1, unit))
yyerror(@1, "internal error: delay.");
else {
double p = pow(10.0,
(double)(unit - pform_get_timeunit()));
double time = atof($1) * p;
verireal *v = new verireal(time);
$$ = new PEFNumber(v);
FILE_NAME($$, @1);
}
verireal *v = new verireal(time);
$$ = new PEFNumber(v);
FILE_NAME($$, @1);
}
}
;
@ -4278,6 +4328,8 @@ statement
{ $$ = 0;
yyerror(@1, "error: Error in while loop condition.");
}
| compressed_statement ';'
{ $$ = $1; }
| delay1 statement_or_null
{ PExpr*del = $1->front();
assert($1->size() == 1);
@ -4421,6 +4473,86 @@ statement
}
;
compressed_statement
: lpvalue K_PLUS_EQ expression
{
PEBinary *t = new PEBinary('+', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MINUS_EQ expression
{
PEBinary *t = new PEBinary('-', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MUL_EQ expression
{
PEBinary *t = new PEBinary('*', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_DIV_EQ expression
{
PEBinary *t = new PEBinary('/', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MOD_EQ expression
{
PEBinary *t = new PEBinary('%', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_AND_EQ expression
{
PEBinary *t = new PEBinary('&', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_OR_EQ expression
{
PEBinary *t = new PEBinary('|', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_XOR_EQ expression
{
PEBinary *t = new PEBinary('^', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_LS_EQ expression
{
PEBShift *t = new PEBShift('l', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_RS_EQ expression
{
PEBShift *t = new PEBShift('r', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_RSS_EQ expression
{
PEBShift *t = new PEBShift('R', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
;
statement_list
: statement_list statement
{ svector<Statement*>*tmp = new svector<Statement*>(*$1, $2);

View File

@ -1542,3 +1542,128 @@ void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig)
assert(0);
}
static void dump_drive(ivl_drive_t drive)
{
switch (drive) {
case IVL_DR_HiZ: fprintf(stderr, "highz"); break;
case IVL_DR_SMALL: fprintf(stderr, "small"); break;
case IVL_DR_MEDIUM: fprintf(stderr, "medium"); break;
case IVL_DR_WEAK: fprintf(stderr, "weak"); break;
case IVL_DR_LARGE: fprintf(stderr, "large"); break;
case IVL_DR_PULL: fprintf(stderr, "pull"); break;
case IVL_DR_STRONG: fprintf(stderr, "strong"); break;
case IVL_DR_SUPPLY: fprintf(stderr, "supply"); break;
}
}
/*
* Routine to dump the nexus information.
*/
void dump_nexus_information(ivl_scope_t scope, ivl_nexus_t nex)
{
unsigned idx, count = ivl_nexus_ptrs(nex);
fprintf(stderr, "Dumping nexus from scope: %s\n",
ivl_scope_name(scope));
for (idx = 0; idx < count; idx += 1) {
ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
ivl_lpm_t lpm = ivl_nexus_ptr_lpm(nex_ptr);
ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr);
ivl_net_logic_t net_logic = ivl_nexus_ptr_log(nex_ptr);
ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr);
fprintf(stderr, " %u (", idx);
dump_drive(ivl_nexus_ptr_drive1(nex_ptr));
fprintf(stderr, "1 ,");
dump_drive(ivl_nexus_ptr_drive0(nex_ptr));
fprintf(stderr, "0) ");
if (lpm) {
ivl_scope_t lpm_scope = ivl_lpm_scope(lpm);
assert(! net_const);
assert(! net_logic);
assert(! sig);
fprintf(stderr, "LPM: ");
fprintf(stderr, "%s:%d ", ivl_lpm_file(lpm),
ivl_lpm_lineno(lpm));
if (scope != lpm_scope) fprintf(stderr, "%s ",
ivl_scope_name(lpm_scope));
switch (ivl_lpm_type(lpm)) {
case IVL_LPM_ABS: fprintf(stderr, "abs"); break;
case IVL_LPM_ADD: fprintf(stderr, "add"); break;
case IVL_LPM_ARRAY: fprintf(stderr, "array"); break;
case IVL_LPM_CAST_INT: fprintf(stderr, "<int>"); break;
case IVL_LPM_CAST_INT2: fprintf(stderr, "<int2>"); break;
case IVL_LPM_CAST_REAL: fprintf(stderr, "<real>"); break;
case IVL_LPM_CONCAT: fprintf(stderr, "concat"); break;
case IVL_LPM_CMP_EEQ: fprintf(stderr, "eeq"); break;
case IVL_LPM_CMP_EQ: fprintf(stderr, "eq"); break;
case IVL_LPM_CMP_GE: fprintf(stderr, "ge"); break;
case IVL_LPM_CMP_GT: fprintf(stderr, "gt"); break;
case IVL_LPM_CMP_NE: fprintf(stderr, "ne"); break;
case IVL_LPM_CMP_NEE: fprintf(stderr, "nee"); break;
case IVL_LPM_DIVIDE: fprintf(stderr, "divide"); break;
case IVL_LPM_FF: fprintf(stderr, "dff"); break;
case IVL_LPM_MOD: fprintf(stderr, "mod"); break;
case IVL_LPM_MULT: fprintf(stderr, "mult"); break;
case IVL_LPM_MUX: fprintf(stderr, "mux"); break;
case IVL_LPM_PART_VP: fprintf(stderr, "part-VP"); break;
case IVL_LPM_PART_PV: fprintf(stderr, "part-PV"); break;
case IVL_LPM_POW: fprintf(stderr, "pow"); break;
case IVL_LPM_RE_AND: fprintf(stderr, "R-AND"); break;
case IVL_LPM_RE_NAND: fprintf(stderr, "R-NAND"); break;
case IVL_LPM_RE_OR: fprintf(stderr, "R-OR"); break;
case IVL_LPM_RE_NOR: fprintf(stderr, "R-NOR"); break;
case IVL_LPM_RE_XNOR: fprintf(stderr, "R-XNOR"); break;
case IVL_LPM_RE_XOR: fprintf(stderr, "R-XOR"); break;
case IVL_LPM_REPEAT: fprintf(stderr, "repeat"); break;
case IVL_LPM_SFUNC: fprintf(stderr, "S-func"); break;
case IVL_LPM_SHIFTL: fprintf(stderr, "shiftl"); break;
case IVL_LPM_SHIFTR: fprintf(stderr, "shiftr"); break;
case IVL_LPM_SIGN_EXT: fprintf(stderr, "sign"); break;
case IVL_LPM_SUB: fprintf(stderr, "sub"); break;
case IVL_LPM_UFUNC: fprintf(stderr, "U-func"); break;
}
} else if (net_const) {
assert(! net_logic);
assert(! sig);
fprintf(stderr, "Const: ");
} else if (net_logic) {
assert(! sig);
fprintf(stderr, "Logic: ");
} else if (sig) {
ivl_scope_t sig_scope = ivl_signal_scope(sig);
fprintf(stderr, "Signal: ");
if (scope != sig_scope) fprintf(stderr, "%s.",
ivl_scope_name(sig_scope));
fprintf(stderr, "%s", ivl_signal_basename(sig));
// HERE: Do we need to add support for an array word or is that an LPM.
if (ivl_signal_local(sig)) fprintf(stderr, " (local)");
switch (ivl_signal_port(sig)) {
case IVL_SIP_INPUT: fprintf(stderr, " input"); break;
case IVL_SIP_OUTPUT: fprintf(stderr, " output"); break;
case IVL_SIP_INOUT: fprintf(stderr, " inout"); break;
case IVL_SIP_NONE: break;
}
switch (ivl_signal_type(sig)) {
case IVL_SIT_NONE: fprintf(stderr, " <no type>"); break;
case IVL_SIT_REG: fprintf(stderr, " reg"); break;
case IVL_SIT_TRI: fprintf(stderr, " tri"); break;
case IVL_SIT_TRI0: fprintf(stderr, " tri0"); break;
case IVL_SIT_TRI1: fprintf(stderr, " tri1"); break;
case IVL_SIT_TRIAND: fprintf(stderr, " triand"); break;
case IVL_SIT_TRIOR: fprintf(stderr, " trior"); break;
case IVL_SIT_UWIRE: fprintf(stderr, " uwire"); break;
}
switch (ivl_signal_data_type(sig)) {
case IVL_VT_VOID: fprintf(stderr, " <void>"); break;
case IVL_VT_NO_TYPE: fprintf(stderr, " <no type>"); break;
case IVL_VT_REAL: fprintf(stderr, " real"); break;
case IVL_VT_BOOL: fprintf(stderr, " bool"); break;
case IVL_VT_LOGIC: fprintf(stderr, " logic"); break;
case IVL_VT_STRING: fprintf(stderr, " string"); break;
}
} else {
fprintf(stderr, "Error: No/missing information!");
}
fprintf(stderr, " (%u)\n", ivl_nexus_ptr_pin(nex_ptr));
}
}

View File

@ -505,7 +505,7 @@ static void emit_number_as_string(ivl_net_const_t net_const)
if (val == '"') fprintf(vlog_out, "\\\"");
else if (val == '\\') fprintf(vlog_out, "\\\\");
/* Print the printable characters. */
else if (isprint(val)) fprintf(vlog_out, "%c", val);
else if (isprint((int)val)) fprintf(vlog_out, "%c", val);
/* Print the non-printable characters as an octal escape. */
else fprintf(vlog_out, "\\%03o", val);
}
@ -641,6 +641,7 @@ void emit_name_of_nexus(ivl_scope_t scope, ivl_nexus_t nex)
/* It is possible that the nexus does not have a name. For this
* case do not print an actual name. */
fprintf(vlog_out, "/* Empty */");
dump_nexus_information(scope, nex);
}
/*

View File

@ -122,4 +122,9 @@ extern uint64_t get_uint64_from_number(ivl_expr_t expr, int *return_type);
*/
extern void free_emitted_scope_list();
/*
* Debug routine to dump the various pieces of nexus information.
*/
extern void dump_nexus_information(ivl_scope_t scope, ivl_nexus_t nex);
#endif /* __vlog95_priv_H */

View File

@ -3118,19 +3118,37 @@ static struct vector_info draw_unary_expr(ivl_expr_t expr, unsigned wid)
local_count += 1;
break;
case '2': /* Cast logic to bool */
assert(ivl_expr_value(sub) == IVL_VT_LOGIC);
res = draw_eval_expr_wid(sub, wid, 0);
case '2': /* Cast expression to bool */
switch (ivl_expr_value(sub)) {
case IVL_VT_BOOL:
res = draw_eval_expr_wid(sub, wid, 0);
break;
/* Handle special case that value is 0 or 1. */
if (res.base == 0 || res.base == 1)
case IVL_VT_LOGIC:
res = draw_eval_expr_wid(sub, wid, 0);
/* Handle special case that value is 0 or 1. */
if (res.base == 0 || res.base == 1)
break;
if (res.base == 2 || res.base == 2) {
res.base = 0;
break;
}
fprintf(vvp_out, " %%cast2 %d, %d, %u;\n", res.base, res.base, res.wid);
break;
if (res.base == 2 || res.base == 2) {
res.base = 0;
case IVL_VT_REAL:
word = draw_eval_real(sub);
res.base = allocate_vector(wid);
res.wid = wid;
fprintf(vvp_out, " %%cvt/vr %d, %d, %u;\n", res.base, word, wid);
clr_word(word);
break;
default:
assert(0);
}
fprintf(vvp_out, " %%cast2 %d, %d, %u;\n", res.base, res.base, res.wid);
break;
case 'i': /* Cast a real value to an integer. */

View File

@ -804,7 +804,8 @@ verinum::V operator <= (const verinum&left, const verinum&right)
{
verinum::V left_pad = verinum::V0;
verinum::V right_pad = verinum::V0;
if (left.has_sign() && right.has_sign()) {
bool signed_calc = left.has_sign() && right.has_sign();
if (signed_calc) {
left_pad = left.get(left.len()-1);
right_pad = right.get(right.len()-1);
@ -816,11 +817,23 @@ verinum::V operator <= (const verinum&left, const verinum&right)
unsigned idx;
for (idx = left.len() ; idx > right.len() ; idx -= 1) {
if (left[idx-1] != right_pad) return verinum::V0;
if (left[idx-1] != right_pad) {
// A change of padding for a negative left argument
// denotes the left value is less than the right.
return (signed_calc &&
(left_pad == verinum::V1)) ? verinum::V1 :
verinum::V0;
}
}
for (idx = right.len() ; idx > left.len() ; idx -= 1) {
if (right[idx-1] != left_pad) return verinum::V1;
if (right[idx-1] != left_pad) {
// A change of padding for a negative right argument
// denotes the left value is not less than the right.
return (signed_calc &&
(right_pad == verinum::V1)) ? verinum::V0 :
verinum::V1;
}
}
idx = right.len();
@ -843,7 +856,8 @@ verinum::V operator < (const verinum&left, const verinum&right)
{
verinum::V left_pad = verinum::V0;
verinum::V right_pad = verinum::V0;
if (left.has_sign() && right.has_sign()) {
bool signed_calc = left.has_sign() && right.has_sign();
if (signed_calc) {
left_pad = left.get(left.len()-1);
right_pad = right.get(right.len()-1);
@ -855,11 +869,23 @@ verinum::V operator < (const verinum&left, const verinum&right)
unsigned idx;
for (idx = left.len() ; idx > right.len() ; idx -= 1) {
if (left[idx-1] != right_pad) return verinum::V0;
if (left[idx-1] != right_pad) {
// A change of padding for a negative left argument
// denotes the left value is less than the right.
return (signed_calc &&
(left_pad == verinum::V1)) ? verinum::V1 :
verinum::V0;
}
}
for (idx = right.len() ; idx > left.len() ; idx -= 1) {
if (right[idx-1] != left_pad) return verinum::V1;
if (right[idx-1] != left_pad) {
// A change of padding for a negative right argument
// denotes the left value is not less than the right.
return (signed_calc &&
(right_pad == verinum::V1)) ? verinum::V0 :
verinum::V1;
}
}
while (idx > 0) {

View File

@ -32,6 +32,8 @@ Architecture::Architecture(perm_string name, const ScopeBase&ref,
Architecture::~Architecture()
{
delete_all(statements_);
ScopeBase::cleanup();
}
Architecture::Statement::Statement()
@ -69,12 +71,15 @@ ComponentInstantiation::ComponentInstantiation(perm_string i, perm_string c,
while (! ports->empty()) {
named_expr_t*cur = ports->front();
ports->pop_front();
port_map_[cur->name()] = cur->expr();
port_map_.insert(make_pair(cur->name(), cur->expr()));
}
}
ComponentInstantiation::~ComponentInstantiation()
{
for(map<perm_string, Expression*>::iterator it = port_map_.begin()
; it != port_map_.end(); ++it)
delete it->second;
}
ProcessStatement::ProcessStatement(perm_string iname,

View File

@ -122,7 +122,7 @@ class ComponentInstantiation : public Architecture::Statement {
perm_string iname_;
perm_string cname_;
std::map<perm_string,Expression*> port_map_;
std::multimap<perm_string,Expression*> port_map_;
};
class ProcessStatement : public Architecture::Statement {

View File

@ -54,10 +54,12 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
return 1;
}
map<perm_string,const InterfacePort*> port_match;
for (map<perm_string,Expression*>::iterator cur = port_map_.begin()
for (multimap<perm_string,Expression*>::const_iterator cur = port_map_.begin()
; cur != port_map_.end() ; ++cur) {
/* check if a port from component instantiation
exists in the component declaration
*/
const InterfacePort*iport = base->find_port(cur->first);
if (iport == 0) {
cerr << get_fileline() << ": error: No port " << cur->first
@ -66,12 +68,25 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
continue;
}
ExpName* tmp;
if (cur->second && (tmp = dynamic_cast<ExpName*>(cur->second)))
errors += tmp->elaborate_rval(ent, arc, iport);
/* It is possible for the port to be explicitly
unconnected. In that case, the Expression will be nil */
if (cur->second)
cur->second->elaborate_expr(ent, arc, iport->type);
}
//each formal (component's) port should be associated at most once
for(multimap<perm_string,Expression*>::const_iterator cur = port_map_.begin()
; cur != port_map_.end() ; ++cur)
if(port_map_.count(cur->first) != 1) {
//at least one port is associated twice or more
cerr << cur->second->get_fileline() << ": error: At least one port is associated"
<< " twice or more in a single component instantiation." << endl;
errors += 1;
}
return errors;
}

View File

@ -30,12 +30,16 @@ int Scope::emit_signals(ostream&out, Entity*entity, Architecture*arc)
{
int errors = 0;
for (map<perm_string,Signal*>::iterator cur = signals_.begin()
; cur != signals_.end() ; ++cur) {
for (map<perm_string,Signal*>::iterator cur = old_signals_.begin()
; cur != old_signals_.end() ; ++cur) {
errors += cur->second->emit(out, entity, arc);
}
for (map<perm_string,Signal*>::iterator cur = new_signals_.begin()
; cur != new_signals_.end() ; ++cur) {
errors += cur->second->emit(out, entity, arc);
}
return errors;
}
@ -43,12 +47,19 @@ int Architecture::emit(ostream&out, Entity*entity)
{
int errors = 0;
for (map<perm_string,struct const_t>::iterator cur = constants_.begin()
; cur != constants_.end() ; ++cur) {
for (map<perm_string,struct const_t*>::iterator cur = old_constants_.begin()
; cur != old_constants_.end() ; ++cur) {
out << "localparam " << cur->first << " = ";
errors += cur->second.val->emit(out, entity, this);
out << ";" << endl;
out << "localparam " << cur->first << " = ";
errors += cur->second->val->emit(out, entity, this);
out << ";" << endl;
}
for (map<perm_string,struct const_t*>::iterator cur = new_constants_.begin()
; cur != new_constants_.end() ; ++cur) {
out << "localparam " << cur->first << " = ";
errors += cur->second->val->emit(out, entity, this);
out << ";" << endl;
}
errors += emit_signals(out, entity, this);
@ -94,7 +105,7 @@ int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc)
out << cname_ << " " << iname_ << "(";
const char*comma = "";
for (map<perm_string,Expression*>::iterator cur = port_map_.begin()
for (multimap<perm_string,Expression*>::iterator cur = port_map_.begin()
; cur != port_map_.end() ; ++cur) {
// Skip unconnected ports
if (cur->second == 0)

View File

@ -79,36 +79,58 @@ void ComponentBase::dump_ports(ostream&out, int indent) const
void Scope::dump_scope(ostream&out) const
{
// Dump types
for (map<perm_string,const VType*>::const_iterator cur = types_.begin()
; cur != types_.end() ; ++cur) {
for (map<perm_string,const VType*>::const_iterator cur = old_types_.begin()
; cur != old_types_.end() ; ++cur) {
out << " " << cur->first << ": ";
cur->second->show(out);
out << endl;
}
for (map<perm_string,const VType*>::const_iterator cur = new_types_.begin()
; cur != new_types_.end() ; ++cur) {
out << " " << cur->first << ": ";
cur->second->show(out);
out << endl;
}
// Dump constants
for (map<perm_string,const_t>::const_iterator cur = constants_.begin()
; cur != constants_.end() ; ++cur) {
for (map<perm_string,const_t*>::const_iterator cur = old_constants_.begin()
; cur != old_constants_.end() ; ++cur) {
out << " constant " << cur->first << " = ";
out << endl;
}
// Dump signal declarations
for (map<perm_string,Signal*>::const_iterator cur = signals_.begin()
; cur != signals_.end() ; ++cur) {
if (cur->second)
cur->second->dump(out, 3);
else
out << " signal " << cur->first.str() << ": ???" << endl;
for (map<perm_string,const_t*>::const_iterator cur = new_constants_.begin()
; cur != new_constants_.end() ; ++cur) {
out << " constant " << cur->first << " = ";
out << endl;
}
// Dump signal declarations
for (map<perm_string,Signal*>::const_iterator cur = old_signals_.begin()
; cur != old_signals_.end() ; ++cur) {
if (cur->second)
cur->second->dump(out, 3);
else
out << " signal " << cur->first.str() << ": ???" << endl;
}
for (map<perm_string,Signal*>::const_iterator cur = new_signals_.begin()
; cur != new_signals_.end() ; ++cur) {
if (cur->second)
cur->second->dump(out, 3);
else
out << " signal " << cur->first.str() << ": ???" << endl;
}
// Dump component declarations
for (map<perm_string,ComponentBase*>::const_iterator cur = components_.begin()
; cur != components_.end() ; ++cur) {
for (map<perm_string,ComponentBase*>::const_iterator cur = old_components_.begin()
; cur != old_components_.end() ; ++cur) {
out << " component " << cur->first << " is" << endl;
cur->second->dump_ports(out);
out << " end component " << cur->first << endl;
}
for (map<perm_string,ComponentBase*>::const_iterator cur = new_components_.begin()
; cur != new_components_.end() ; ++cur) {
out << " component " << cur->first << " is" << endl;
cur->second->dump_ports(out);
out << " end component " << cur->first << endl;
}
}
void Entity::dump(ostream&out, int indent) const

View File

@ -33,6 +33,9 @@ ComponentBase::ComponentBase(perm_string name)
ComponentBase::~ComponentBase()
{
for(std::vector<InterfacePort*>::iterator it = ports_.begin()
; it != ports_.end(); ++it)
delete *it;
}
void ComponentBase::set_interface(std::list<InterfacePort*>*ports)
@ -60,6 +63,9 @@ Entity::Entity(perm_string name)
Entity::~Entity()
{
for(map<perm_string,Architecture*>::reverse_iterator it = arch_.rbegin()
; it != arch_.rend(); ++it)
delete it->second;
}
Architecture* Entity::add_architecture(Architecture*that)

View File

@ -21,6 +21,7 @@
# include "StringHeap.h"
# include "LineInfo.h"
# include "entity.h"
# include <inttypes.h>
# include <list>
# include <vector>
@ -322,6 +323,7 @@ class ExpName : public Expression {
public: // Base methods
int elaborate_lval(Entity*ent, Architecture*arc, bool);
int elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*);
const VType* probe_type(Entity*ent, Architecture*arc) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
int emit(ostream&out, Entity*ent, Architecture*arc);

View File

@ -71,6 +71,44 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
return errors;
}
int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lval)
{
int errors = 0;
if (const InterfacePort*cur = ent->find_port(name_)) {
/* IEEE 1076-2008, p.80:
* For a formal port IN, associated port should be IN, OUT, INOUT or BUFFER
* For a formal port OUT, associated port should be OUT, INOUT or BUFFER
* For a formal port INOUT, associated prot should be OUT, INOUT or BUFFER
* For a formal port BUFFER, associated port should be OUT, INOUT or BUFFER
*/
switch(lval->mode) {
case PORT_OUT:
//case PORT_INOUT:
if (cur->mode == PORT_IN) {
cerr << get_fileline() << ": error: Connecting "
"formal output port " << lval->name << " to actual input port "
<< name_ << "." << endl;
errors += 1;
}
break;
case PORT_IN:
case PORT_NONE:
default:
break;
}
} else if (Signal* fs = arc->find_signal(name_)) {
/* OK */
} else {
cerr << get_fileline() << ": error: No port or signal " << name_
<< " to be used as r-value." << endl;
errors += 1;
}
return errors;
}
int ExpNameALL::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
{
return Expression::elaborate_lval(ent, arc, is_sequ);

View File

@ -165,7 +165,7 @@ static void import_ieee_use_std_logic_1164(ActiveScope*res, perm_string name)
if (all_flag || name == "std_logic_vector") {
vector<VTypeArray::range_t> dims (1);
res->bind_name(perm_string::literal("std_logic_vector"),
new VTypeArray(&primitive_STDLOGIC, dims, false));
new VTypeArray(primitive_STDLOGIC, dims, false));
}
}
@ -176,12 +176,12 @@ static void import_ieee_use_numeric_bit(ActiveScope*res, perm_string name)
if (all_flag || name == "signed") {
vector<VTypeArray::range_t> dims (1);
res->bind_name(perm_string::literal("signed"),
new VTypeArray(&primitive_STDLOGIC, dims, true));
new VTypeArray(primitive_STDLOGIC, dims, true));
}
if (all_flag || name == "unsigned") {
vector<VTypeArray::range_t> dims (1);
res->bind_name(perm_string::literal("unsigned"),
new VTypeArray(&primitive_BIT, dims, false));
new VTypeArray(primitive_BIT, dims, false));
}
}
@ -192,12 +192,12 @@ static void import_ieee_use_numeric_std(ActiveScope*res, perm_string name)
if (all_flag || name == "signed") {
vector<VTypeArray::range_t> dims (1);
res->bind_name(perm_string::literal("signed"),
new VTypeArray(&primitive_STDLOGIC, dims, true));
new VTypeArray(primitive_STDLOGIC, dims, true));
}
if (all_flag || name == "unsigned") {
vector<VTypeArray::range_t> dims (1);
res->bind_name(perm_string::literal("unsigned"),
new VTypeArray(&primitive_STDLOGIC, dims, false));
new VTypeArray(primitive_STDLOGIC, dims, false));
}
}
@ -219,22 +219,21 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na
}
}
const VTypePrimitive* primitive_BOOLEAN = new VTypePrimitive(VTypePrimitive::BOOLEAN);
const VTypePrimitive* primitive_BIT = new VTypePrimitive(VTypePrimitive::BIT);
const VTypePrimitive* primitive_INTEGER = new VTypePrimitive(VTypePrimitive::INTEGER);
const VTypePrimitive* primitive_STDLOGIC = new VTypePrimitive(VTypePrimitive::STDLOGIC);
const VTypePrimitive primitive_BOOLEAN (VTypePrimitive::BOOLEAN);
const VTypePrimitive primitive_BIT (VTypePrimitive::BIT);
const VTypePrimitive primitive_INTEGER (VTypePrimitive::INTEGER);
const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC);
const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector<VTypeArray::range_t> (1));
const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector<VTypeArray::range_t> (1));
const VTypeArray* primitive_BIT_VECTOR = new VTypeArray(primitive_BIT, vector<VTypeArray::range_t> (1));
const VTypeArray* primitive_BOOL_VECTOR = new VTypeArray(primitive_BOOLEAN, vector<VTypeArray::range_t> (1));
void generate_global_types(ActiveScope*res)
{
res->bind_name(perm_string::literal("boolean"), &primitive_BOOLEAN);
res->bind_name(perm_string::literal("bit"), &primitive_BIT);
res->bind_name(perm_string::literal("integer"), &primitive_INTEGER);
res->bind_name(perm_string::literal("std_logic"), &primitive_STDLOGIC);
res->bind_name(perm_string::literal("bit_vector"),&primitive_BOOL_VECTOR);
res->bind_name(perm_string::literal("boolean"), primitive_BOOLEAN);
res->bind_name(perm_string::literal("bit"), primitive_BIT);
res->bind_name(perm_string::literal("integer"), primitive_INTEGER);
res->bind_name(perm_string::literal("std_logic"), primitive_STDLOGIC);
res->bind_name(perm_string::literal("bit_vector"),primitive_BOOL_VECTOR);
}
void library_set_work_path(const char*path)

View File

@ -59,6 +59,7 @@ const char*dump_libraries_path = 0;
extern void dump_libraries(ostream&file);
extern void parser_cleanup();
static void process_debug_token(const char*word)
{
@ -158,21 +159,25 @@ int main(int argc, char*argv[])
dump_design_entities(file);
}
if (errors > 0)
if (errors > 0) {
parser_cleanup();
return 2;
}
errors = elaborate_entities();
if (errors > 0) {
fprintf(stderr, "%d errors elaborating design.\n", errors);
parser_cleanup();
return 3;
}
errors = emit_entities();
if (errors > 0) {
fprintf(stderr, "%d errors emitting design.\n", errors);
parser_cleanup();
return 4;
}
lex_strings.cleanup();
parser_cleanup();
return 0;
}

View File

@ -27,14 +27,20 @@ Package::Package(perm_string n, const ScopeBase&ref)
Package::~Package()
{
ScopeBase::cleanup();
}
void Package::write_to_stream(ostream&fd) const
{
fd << "package " << name_ << " is" << endl;
for (map<perm_string,ComponentBase*>::const_iterator cur = components_.begin()
; cur != components_.end() ; ++cur) {
for (map<perm_string,ComponentBase*>::const_iterator cur = old_components_.begin()
; cur != old_components_.end() ; ++cur) {
cur->second->write_to_stream(fd);
}
for (map<perm_string,ComponentBase*>::const_iterator cur = new_components_.begin()
; cur != new_components_.end() ; ++cur) {
cur->second->write_to_stream(fd);
}

View File

@ -39,6 +39,7 @@
# include <cstdarg>
# include <cstring>
# include <list>
# include <stack>
# include <map>
# include <vector>
# include "parse_types.h"
@ -77,7 +78,7 @@ extern int yylex(union YYSTYPE*yylvalp,YYLTYPE*yyllocp,yyscan_t yyscanner);
* manage lexical scopes.
*/
static ActiveScope*active_scope = new ActiveScope;
static list<ActiveScope*> scope_stack;
static stack<ActiveScope*> scope_stack;
/*
* When a scope boundary starts, call the push_scope function to push
@ -89,7 +90,7 @@ static list<ActiveScope*> scope_stack;
static void push_scope(void)
{
assert(active_scope);
scope_stack.push_front(active_scope);
scope_stack.push(active_scope);
active_scope = new ActiveScope (active_scope);
}
@ -97,8 +98,8 @@ static void pop_scope(void)
{
delete active_scope;
assert(scope_stack.size() > 0);
active_scope = scope_stack.front();
scope_stack.pop_front();
active_scope = scope_stack.top();
scope_stack.pop();
}
@ -107,6 +108,31 @@ void preload_global_types(void)
generate_global_types(active_scope);
}
//Remove the scope created at the beginning of parser's work.
//After the parsing active_scope should keep it's address
static void delete_global_scope(void)
{
active_scope->destroy_global_scope();
delete active_scope;
}
//delete global entities that were gathered over the parsing process
static void delete_design_entities(void)
{
for(map<perm_string,Entity*>::iterator cur = design_entities.begin()
; cur != design_entities.end(); ++cur)
delete cur->second;
}
//clean the mess caused by the parser
void parser_cleanup(void)
{
delete_design_entities();
delete_global_scope();
lex_strings.cleanup();
}
const VType*parse_type_by_name(perm_string name)
{
return active_scope->find_type(name);
@ -473,7 +499,10 @@ component_declaration
}
ComponentBase*comp = new ComponentBase(name);
if ($4) comp->set_interface($4);
if ($4) {
comp->set_interface($4);
delete $4;
}
active_scope->bind_name(name, comp);
delete[]$2;
if ($7) delete[] $7;
@ -492,6 +521,7 @@ component_instantiation_statement
{ perm_string iname = lex_strings.make($1);
perm_string cname = lex_strings.make($4);
ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $5);
delete $5;
FILE_NAME(tmp, @1);
delete[]$1;
delete[]$4;
@ -681,7 +711,7 @@ entity_declaration
errormsg(@1, "Syntax error in entity clause. Closing name doesn't match.\n");
yyerrok;
}
delete $7;
delete[]$7;
}
}
| K_entity error K_end K_entity_opt identifier_opt ';'

View File

@ -18,61 +18,122 @@
*/
# include "scope.h"
# include <algorithm>
# include <iostream>
# include <iterator>
using namespace std;
ScopeBase::ScopeBase(const ScopeBase&ref)
{
constants_ = ref.constants_;
signals_ = ref.signals_;
components_ = ref.components_;
types_ = ref.types_;
merge(ref.old_constants_.begin(), ref.old_constants_.end(),
ref.new_constants_.begin(), ref.new_constants_.end(),
insert_iterator<map<perm_string, struct const_t*> >(
old_constants_, old_constants_.end())
);
merge(ref.old_signals_.begin(), ref.old_signals_.end(),
ref.new_signals_.begin(), ref.new_signals_.end(),
insert_iterator<map<perm_string, Signal*> >(
old_signals_, old_signals_.end())
);
merge(ref.old_components_.begin(), ref.old_components_.end(),
ref.new_components_.begin(), ref.new_components_.end(),
insert_iterator<map<perm_string, ComponentBase*> >(
old_components_, old_components_.end())
);
merge(ref.old_types_.begin(), ref.old_types_.end(),
ref.new_types_.begin(), ref.new_types_.end(),
insert_iterator<map<perm_string, const VType*> >(
old_types_, old_types_.end())
);
}
ScopeBase::~ScopeBase()
{
//freeing of member objects is performed by child classes
}
void ScopeBase::cleanup()
{
/*
* A parent scope is destroyed only if all child scopes
* were previously destroyed. There for we can delete all
* objects that were defined in this scope, leaving
* objects from the other scopes untouched.
*/
delete_all(new_signals_);
delete_all(new_components_);
delete_all(new_types_);
delete_all(new_constants_);
}
const VType*ScopeBase::find_type(perm_string by_name)
{
map<perm_string,const VType*>::const_iterator cur = types_.find(by_name);
if (cur == types_.end())
return 0;
else
map<perm_string,const VType*>::const_iterator cur = new_types_.find(by_name);
if (cur == new_types_.end()) {
cur = old_types_.find(by_name);
if (cur == old_types_.end())
return 0;
else
return cur->second;
} else
return cur->second;
}
bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp)
{
map<perm_string,const_t>::const_iterator cur = constants_.find(by_name);
if (cur == constants_.end())
return false;
typ = cur->second.typ;
exp = cur->second.val;
return true;
map<perm_string,struct const_t*>::const_iterator cur = new_constants_.find(by_name);
if (cur == new_constants_.end()) {
cur = old_constants_.find(by_name);
if (cur == old_constants_.end())
return false;
else {
typ = cur->second->typ;
exp = cur->second->val;
return true;
}
} else {
typ = cur->second->typ;
exp = cur->second->val;
return true;
}
}
void ScopeBase::do_use_from(const ScopeBase*that)
{
for (map<perm_string,ComponentBase*>::const_iterator cur = that->components_.begin()
; cur != that->components_.end() ; ++ cur) {
for (map<perm_string,ComponentBase*>::const_iterator cur = that->old_components_.begin()
; cur != that->old_components_.end() ; ++ cur) {
if (cur->second == 0)
continue;
components_[cur->first] = cur->second;
old_components_[cur->first] = cur->second;
}
for (map<perm_string,ComponentBase*>::const_iterator cur = that->new_components_.begin()
; cur != that->new_components_.end() ; ++ cur) {
if (cur->second == 0)
continue;
old_components_[cur->first] = cur->second;
}
for (map<perm_string,const VType*>::const_iterator cur = that->types_.begin()
; cur != that->types_.end() ; ++ cur) {
for (map<perm_string,const VType*>::const_iterator cur = that->old_types_.begin()
; cur != that->old_types_.end() ; ++ cur) {
if (cur->second == 0)
continue;
types_[cur->first] = cur->second;
old_types_[cur->first] = cur->second;
}
for (map<perm_string,const VType*>::const_iterator cur = that->new_types_.begin()
; cur != that->new_types_.end() ; ++ cur) {
if (cur->second == 0)
continue;
old_types_[cur->first] = cur->second;
}
for (map<perm_string,const_t>::const_iterator cur = that->constants_.begin()
; cur != that->constants_.end() ; ++ cur) {
constants_[cur->first] = cur->second;
for (map<perm_string,const_t*>::const_iterator cur = that->old_constants_.begin()
; cur != that->old_constants_.end() ; ++ cur) {
old_constants_[cur->first] = cur->second;
}
for (map<perm_string,const_t*>::const_iterator cur = that->new_constants_.begin()
; cur != that->new_constants_.end() ; ++ cur) {
old_constants_[cur->first] = cur->second;
}
}
@ -87,18 +148,27 @@ Scope::~Scope()
ComponentBase* Scope::find_component(perm_string by_name)
{
map<perm_string,ComponentBase*>::const_iterator cur = components_.find(by_name);
if (cur == components_.end())
return 0;
else
map<perm_string,ComponentBase*>::const_iterator cur = new_components_.find(by_name);
if (cur == new_components_.end()) {
cur = old_components_.find(by_name);
if (cur == old_components_.end())
return 0;
else
return cur->second;
} else
return cur->second;
}
Signal* Scope::find_signal(perm_string by_name)
{
map<perm_string,Signal*>::const_iterator cur = signals_.find(by_name);
if (cur == signals_.end())
return 0;
else
map<perm_string,Signal*>::const_iterator cur = new_signals_.find(by_name);
if (cur == new_signals_.end()) {
cur = old_signals_.find(by_name);
if (cur == old_signals_.end())
return 0;
else
return cur->second;
} else {
return cur->second;
}
}

View File

@ -19,17 +19,28 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <algorithm>
# include <list>
# include <map>
# include "StringHeap.h"
# include "entity.h"
# include "expression.h"
# include "vsignal.h"
class Architecture;
class ComponentBase;
class Entity;
class Expression;
class Signal;
class VType;
template<typename T>
struct delete_object{
void operator()(T* item) { delete item; }
};
template<typename T>
struct delete_pair_second{
void operator()(pair<perm_string, T*> item){ delete item.second; }
};
class ScopeBase {
public:
@ -40,18 +51,37 @@ class ScopeBase {
const VType* find_type(perm_string by_name);
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp);
protected:
void cleanup();
//containers' cleaning helper functions
template<typename T> void delete_all(list<T*>& c)
{
for_each(c.begin(), c.end(), ::delete_object<T>());
}
template<typename T> void delete_all(map<perm_string, T*>& c)
{
for_each(c.begin(), c.end(), ::delete_pair_second<T>());
}
// Signal declarations...
std::map<perm_string,Signal*> signals_;
std::map<perm_string,Signal*> old_signals_; //previous scopes
std::map<perm_string,Signal*> new_signals_; //current scope
// Component declarations...
std::map<perm_string,ComponentBase*> components_;
std::map<perm_string,ComponentBase*> old_components_; //previous scopes
std::map<perm_string,ComponentBase*> new_components_; //current scope
// Type declarations...
std::map<perm_string,const VType*> types_;
std::map<perm_string,const VType*> old_types_; //previous scopes
std::map<perm_string,const VType*> new_types_; //current scope
// Constant declarations...
struct const_t {
~const_t() {delete typ; delete val;}
const_t(const VType*t, Expression* v) : typ(t), val(v) {};
const VType*typ;
Expression*val;
};
std::map<perm_string, struct const_t> constants_;
std::map<perm_string, struct const_t*> old_constants_; //previous scopes
std::map<perm_string, struct const_t*> new_constants_; //current scope
void do_use_from(const ScopeBase*that);
};
@ -90,20 +120,44 @@ class ActiveScope : public ScopeBase {
void use_from(const ScopeBase*that) { do_use_from(that); }
/* All bind_name function check if the given name was present
* in previous scopes. If it is found, it is erased (but the pointer
* is not freed), in order to implement name shadowing. The pointer
* be freed only in the scope where the object was defined. This is
* done in ScopeBase::cleanup() function .*/
void bind_name(perm_string name, Signal*obj)
{ signals_[name] = obj; }
{ map<perm_string, Signal*>::iterator it;
if((it = old_signals_.find(name)) != old_signals_.end() )
old_signals_.erase(it);
new_signals_[name] = obj;
}
void bind_name(perm_string name, ComponentBase*obj)
{ components_[name] = obj; }
{ map<perm_string, ComponentBase*>::iterator it;
if((it = old_components_.find(name)) != old_components_.end() )
old_components_.erase(it);
new_components_[name] = obj;
}
void bind_name(perm_string name, const VType*obj)
{ types_[name] = obj; }
void bind_name(perm_string name, const VType* t)
{ map<perm_string, const VType*>::iterator it;
if((it = old_types_.find(name)) != old_types_.end() )
old_types_.erase(it);
new_types_[name] = t;
}
void bind_name(perm_string name, const VType*obj, Expression*val)
{ map<perm_string, const_t*>::iterator it;
if((it = old_constants_.find(name)) != old_constants_.end() )
old_constants_.erase(it);
new_constants_[name] = new const_t(obj, val);
}
void destroy_global_scope()
{
const_t&tmp = constants_[name];
tmp.typ = obj;
tmp.val = val;
cleanup();
}
};

View File

@ -89,10 +89,10 @@ class VTypePrimitive : public VType {
type_t type_;
};
extern const VTypePrimitive primitive_BOOLEAN;
extern const VTypePrimitive primitive_BIT;
extern const VTypePrimitive primitive_INTEGER;
extern const VTypePrimitive primitive_STDLOGIC;
extern const VTypePrimitive* primitive_BOOLEAN;
extern const VTypePrimitive* primitive_BIT;
extern const VTypePrimitive* primitive_INTEGER;
extern const VTypePrimitive* primitive_STDLOGIC;
/*
* An array is a compound N-dimensional array of element type. The

View File

@ -31,7 +31,7 @@ void VType::write_to_stream(ostream&fd) const
void VTypeArray::write_to_stream(ostream&fd) const
{
// Special case: std_logic_vector
if (etype_ == &primitive_STDLOGIC) {
if (etype_ == primitive_STDLOGIC) {
fd << "std_logic_vector";
if (ranges_.size() > 0) {
assert(ranges_.size() < 2);