Merge branch 'master' into work5

Conflicts:
	vhdlpp/parse.y
This commit is contained in:
Stephen Williams 2011-03-29 09:37:28 -07:00
commit 1688828b4d
15 changed files with 295 additions and 41 deletions

View File

@ -3163,10 +3163,10 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
{
expr_type_ = IVL_VT_LOGIC;
expr_width_ = value_->len();
min_width_ = 1;
min_width_ = expr_width_;
signed_flag_ = value_->has_sign();
if ((mode < LOSSLESS) && !value_->has_len())
if ((mode < LOSSLESS) && !value_->has_len() && !value_->is_single())
mode = LOSSLESS;
return expr_width_;

View File

@ -49,7 +49,7 @@ valid options include:
-f <path>
Read ivlpp input files from a file list. There can be no
more then one file list.
more than one file list.
-I <dir>
Add a directory to the include path. Normally, only "." is

View File

@ -329,6 +329,14 @@ TU [munpf]
return BASED_NUMBER; }
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
return BASED_NUMBER; }
\'[01xzXZ] {
if (generation_flag < GN_VER2005_SV) {
cerr << yylloc.text << ":" << yylloc.first_line << ": warning: "
<< "Using SystemVerilog 'N bit vector. Use at least "
<< "-g2005-sv to remove this warning." << endl;
}
yylval.number = make_unsized_binary(yytext);
return BASED_NUMBER; }
[0-9][0-9_]* {
yylval.number = make_unsized_dec(yytext);
@ -684,6 +692,7 @@ void lex_end_table()
verinum*make_unsized_binary(const char*txt)
{
bool sign_flag = false;
bool single_flag = false;
const char*ptr = txt;
assert(*ptr == '\'');
ptr += 1;
@ -693,8 +702,13 @@ verinum*make_unsized_binary(const char*txt)
ptr += 1;
}
assert(tolower(*ptr) == 'b');
ptr += 1;
assert((tolower(*ptr) == 'b') || (generation_flag >= GN_VER2005_SV));
if (tolower(*ptr) == 'b') {
ptr += 1;
} else {
assert(sign_flag == false);
single_flag = true;
}
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
ptr += 1;
@ -734,6 +748,7 @@ verinum*make_unsized_binary(const char*txt)
verinum*out = new verinum(bits, size, false);
out->has_sign(sign_flag);
out->is_single(single_flag);
delete[]bits;
return out;
}

View File

@ -1669,7 +1669,7 @@ class NetExpr : public LineInfo {
// rise/fall/decay: Attach these delays to the driver for the
// expression output.
//
// drive0/drive1: Attach these strengths tp the driver for
// drive0/drive1: Attach these strengths to the driver for
// the expression output.
virtual NetNet*synthesize(Design*des, NetScope*scope, NetExpr*root);

26
parse.y
View File

@ -3463,6 +3463,19 @@ dimensions
tmp->push_back(index);
$$ = tmp;
}
| '[' expression ']'
{ if (generation_flag < GN_VER2005_SV) {
warn_count += 1;
cerr << @2 << ": warning: Use of SystemVerilog [size] dimension. "
<< "Use at least -g2005-sv to remove this warning." << endl;
}
list<index_component_t> *tmp = new list<index_component_t>;
index_component_t index;
index.msb = new PENumber(new verinum((uint64_t)0, integer_width));
index.lsb = new PEBinary('-', $2, new PENumber(new verinum((uint64_t)1, integer_width)));
tmp->push_back(index);
$$ = tmp;
}
| dimensions '[' expression ':' expression ']'
{ list<index_component_t> *tmp = $1;
index_component_t index;
@ -3471,6 +3484,19 @@ dimensions
tmp->push_back(index);
$$ = tmp;
}
| dimensions '[' expression ']'
{ if (generation_flag < GN_VER2005_SV) {
warn_count += 1;
cerr << @2 << ": warning: Use of SystemVerilog [size] dimension. "
<< "Use at least -g2005-sv to remove this warning." << endl;
}
list<index_component_t> *tmp = $1;
index_component_t index;
index.msb = new PENumber(new verinum((uint64_t)0, integer_width));
index.lsb = new PEBinary('-', $3, new PENumber(new verinum((uint64_t)1, integer_width)));
tmp->push_back(index);
$$ = tmp;
}
/* This is used to express the return type of a function. */
function_range_or_type_opt

View File

@ -116,7 +116,7 @@ void parm_to_defparam_list(const string&param)
if (*value == '"') { // string type
char *buf = strdup (value);
char *buf_ptr = buf+1;
// Parse untill another '"' or '\0'
// Parse until another '"' or '\0'
while (*buf_ptr != '"' && *buf_ptr != '\0') {
buf_ptr++;
// Check for escape, especially '\"', which does not mean the

View File

@ -116,7 +116,7 @@ static int draw_stask_display(vhdl_procedural *proc,
switch (*p) {
case 'm':
// TOOD: we can get the module name via attributes
// TODO: we can get the module name via attributes
cerr << "Warning: no VHDL translation for %m format code"
<< endl;
break;
@ -1603,7 +1603,7 @@ int draw_utask(vhdl_procedural *proc, stmt_container *container,
// TODO: adding some comments to the output would be helpful
// TOOD: this completely ignores parameters!
// TODO: this completely ignores parameters!
draw_stmt(proc, container, ivl_scope_def(tscope), false);
return 0;

View File

@ -43,12 +43,12 @@ extern "C" long int lround(double x)
static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c);
verinum::verinum()
: bits_(0), nbits_(0), has_len_(false), has_sign_(false), string_flag_(false)
: bits_(0), nbits_(0), has_len_(false), has_sign_(false), is_single_(false), string_flag_(false)
{
}
verinum::verinum(const V*bits, unsigned nbits, bool has_len__)
: has_len_(has_len__), has_sign_(false), string_flag_(false)
: has_len_(has_len__), has_sign_(false), is_single_(false), string_flag_(false)
{
nbits_ = nbits;
bits_ = new V [nbits];
@ -111,7 +111,7 @@ static string process_verilog_string_quotes(const string&str)
}
verinum::verinum(const string&s)
: has_len_(true), has_sign_(false), string_flag_(true)
: has_len_(true), has_sign_(false), is_single_(false), string_flag_(true)
{
string str = process_verilog_string_quotes(s);
nbits_ = str.length() * 8;
@ -149,7 +149,7 @@ verinum::verinum(const string&s)
}
verinum::verinum(verinum::V val, unsigned n, bool h)
: has_len_(h), has_sign_(false), string_flag_(false)
: has_len_(h), has_sign_(false), is_single_(false), string_flag_(false)
{
nbits_ = n;
bits_ = new V[nbits_];
@ -158,7 +158,7 @@ verinum::verinum(verinum::V val, unsigned n, bool h)
}
verinum::verinum(uint64_t val, unsigned n)
: has_len_(true), has_sign_(false), string_flag_(false)
: has_len_(true), has_sign_(false), is_single_(false), string_flag_(false)
{
nbits_ = n;
bits_ = new V[nbits_];
@ -171,7 +171,7 @@ verinum::verinum(uint64_t val, unsigned n)
/* The second argument is not used! It is there to make this
* constructor unique. */
verinum::verinum(double val, bool)
: has_len_(false), has_sign_(true), string_flag_(false)
: has_len_(false), has_sign_(true), is_single_(false), string_flag_(false)
{
bool is_neg = false;
double fraction;
@ -281,6 +281,7 @@ verinum::verinum(const verinum&that)
bits_ = new V[nbits_];
has_len_ = that.has_len_;
has_sign_ = that.has_sign_;
is_single_ = that.is_single_;
for (unsigned idx = 0 ; idx < nbits_ ; idx += 1)
bits_[idx] = that.bits_[idx];
}
@ -292,6 +293,7 @@ verinum::verinum(const verinum&that, unsigned nbits)
bits_ = new V[nbits_];
has_len_ = true;
has_sign_ = that.has_sign_;
is_single_ = false;
unsigned copy = nbits;
if (copy > that.nbits_)
@ -300,7 +302,7 @@ verinum::verinum(const verinum&that, unsigned nbits)
bits_[idx] = that.bits_[idx];
if (copy < nbits_) {
if (has_sign_) {
if (has_sign_ || that.is_single_) {
for (unsigned idx = copy ; idx < nbits_ ; idx += 1)
bits_[idx] = bits_[idx-1];
} else {
@ -311,7 +313,7 @@ verinum::verinum(const verinum&that, unsigned nbits)
}
verinum::verinum(int64_t that)
: has_len_(false), has_sign_(true), string_flag_(false)
: has_len_(false), has_sign_(true), is_single_(false), string_flag_(false)
{
int64_t tmp;
@ -348,6 +350,7 @@ verinum& verinum::operator= (const verinum&that)
has_len_ = that.has_len_;
has_sign_ = that.has_sign_;
is_single_ = that.is_single_;
string_flag_ = that.string_flag_;
return *this;
}
@ -570,9 +573,9 @@ verinum pad_to_width(const verinum&that, unsigned width)
}
verinum::V pad = that[that.len()-1];
if (pad==verinum::V1 && !that.has_sign())
if (pad==verinum::V1 && !that.has_sign() && !that.is_single())
pad = verinum::V0;
if (that.has_len() && !that.has_sign()) {
if (that.has_len() && !that.has_sign() && !that.is_single()) {
if (pad==verinum::Vx)
pad = verinum::V0;
if (pad==verinum::Vz)
@ -606,9 +609,9 @@ verinum cast_to_width(const verinum&that, unsigned width)
}
verinum::V pad = that[that.len()-1];
if (pad==verinum::V1 && !that.has_sign())
if (pad==verinum::V1 && !that.has_sign() && !that.is_single())
pad = verinum::V0;
if (that.has_len() && !that.has_sign()) {
if (that.has_len() && !that.has_sign() && !that.is_single()) {
if (pad==verinum::Vx)
pad = verinum::V0;
if (pad==verinum::Vz)

View File

@ -70,6 +70,10 @@ class verinum {
bool has_sign(bool flag) { has_sign_ = flag; return has_sign_; }
bool has_sign() const { return has_sign_; }
// A number "is single" if it comes from a SystemVerilog 'N bit vector
bool is_single(bool flag) { is_single_ = flag; return is_single_; }
bool is_single() const { return is_single_; }
// A number is "defined" if there are no x or z bits in its value.
bool is_defined() const;
bool is_zero() const;
@ -103,6 +107,7 @@ class verinum {
unsigned nbits_;
bool has_len_;
bool has_sign_;
bool is_single_;
// These are some convenience flags that help us do a better
// job of pretty-printing values.

View File

@ -116,7 +116,7 @@ void Architecture::dump(ostream&out, perm_string of_entity) const
void Architecture::Statement::dump(ostream&out) const
{
out << " Architecutre::Statement at file=" << get_fileline() << endl;
out << " Architecture::Statement at file=" << get_fileline() << endl;
}
void Signal::dump(ostream&out) const

View File

@ -37,9 +37,9 @@ class Expression : public LineInfo {
Expression();
virtual ~Expression() =0;
// The emit virtual method is called bu architecture emit to
// The emit virtual method is called by architecture emit to
// output the generated code for the expression. The derived
// class fills in the details of what exactly happend.
// class fills in the details of what exactly happened.
virtual int emit(ostream&out, Entity*ent, Architecture*arc) =0;
// The evaluate virtual method tries to evaluate expressions
@ -49,9 +49,9 @@ class Expression : public LineInfo {
virtual bool evaluate(int64_t&val) const;
// This method returns true if the drawn Verilog for this
// expression is a primary. A containing expressin can use
// expression is a primary. A containing expression can use
// this method to know if it needs to wrap parentheses. This
// is somewhile optional, so it is better to return false if
// is somewhat optional, so it is better to return false if
// not certain. The default implementation does return false.
virtual bool is_primary(void) const;

View File

@ -166,7 +166,7 @@ architecture_body
FILE_NAME(tmp, @1);
bind_architecture_to_entity($4, tmp);
if ($11 && tmp->get_name() != $11)
errormsg(@2, "Architecture name doesn't match closing name\n");
errormsg(@2, "Architecture name doesn't match closing name.\n");
delete[]$2;
delete[]$4;
delete $8;
@ -215,6 +215,31 @@ association_list
| association_element
;
//TODO: this list is only a sketch
binding_indication
: K_use entity_aspect_opt
port_map_aspect_opt
generic_map_aspect_opt
;
binding_indication_semicolon_opt
: binding_indication ';'
|
;
block_configuration
: K_for IDENTIFIER
use_clauses_opt
configuration_items_opt
K_end K_for ';'
{ delete[] $2; }
;
block_configuration_opt
: block_configuration
|
;
block_declarative_item
: K_signal identifier_list ':' subtype_indication ';'
{ /* Save the signal declaration in the block_signals map. */
@ -231,16 +256,17 @@ block_declarative_item
port_clause_opt
K_end K_component identifier_opt ';'
{ perm_string name = lex_strings.make($2);
if ($7 && name != $7) {
errormsg(@7, "Identifier %s doesn't match component name %s\n",
if($7) {
if (name != $7)
errormsg(@7, "Identifier %s doesn't match component name %s.\n",
$7, name.str());
}
delete[] $7;
}
ComponentBase*comp = new ComponentBase(name);
if ($4) comp->set_interface($4);
block_components[name] = comp;
delete[]$2;
delete[]$7;
}
/* Various error handling rules for block_declarative_item... */
@ -251,7 +277,12 @@ block_declarative_item
{ errormsg(@1, "Syntax error in block declarations.\n"); yyerrok; }
| K_component IDENTIFIER K_is_opt error K_end K_component identifier_opt ';'
{ errormsg(@4, "Syntax error in component declaration.\n"); yyerrok; }
{ errormsg(@4, "Syntax error in component declaration.\n");
delete[] $2;
if($7) {
delete[] $7;
}
yyerrok; }
;
/*
@ -269,6 +300,13 @@ block_declarative_items_opt
|
;
component_configuration
: K_for component_specification
binding_indication_semicolon_opt
block_configuration_opt
K_end K_for ';'
;
component_instantiation_statement
: IDENTIFIER ':' IDENTIFIER port_map_aspect_opt ';'
{ sorrymsg(@1, "Component instantiation statements are not supported.\n");
@ -284,6 +322,28 @@ component_instantiation_statement
}
;
component_specification
: instantiation_list ':' IDENTIFIER
{ sorrymsg(@1, "Component specifications are not supported.\n");
delete[] $3
}
;
configuration_declaration
: K_configuration IDENTIFIER K_of IDENTIFIER K_is
configuration_declarative_part
block_configuration
K_end K_configuration_opt identifier_opt ';'
{
sorrymsg(@1, "Configuration declaration is not yet supported.\n");
}
| K_configuration error K_end K_configuration_opt identifier_opt ';'
{ errormsg(@2, "Too many errors, giving up on configuration declaration.\n");
if($5) delete $5;
yyerrok;
}
;
concurrent_signal_assignment_statement
: name LEQ waveform ';'
{ ExpName*name = dynamic_cast<ExpName*> ($1);
@ -306,6 +366,35 @@ concurrent_statement
: component_instantiation_statement
| concurrent_signal_assignment_statement
;
//TODO: this list is only a sketch. It must be filled out later
configuration_declarative_item
: use_clause
;
configuration_declarative_items
: configuration_declarative_items configuration_declarative_item
| configuration_declarative_item
;
configuration_declarative_part
: configuration_declarative_items
|
;
configuration_item
: block_configuration
| component_configuration
;
configuration_items
: configuration_items configuration_item
| configuration_item
;
configuration_items_opt
: configuration_items
|
;
context_clause : context_items | ;
@ -334,6 +423,17 @@ design_units
direction : K_to { $$ = false; } | K_downto { $$ = true; } ;
/* As an entity is declared, add it to the map of design entities. */
entity_aspect
: K_entity IDENTIFIER {sorrymsg(@1, "Entity aspect not yet supported.\n"); delete $2;}
| K_configuration IDENTIFIER {sorrymsg(@1, "Instatiation lists not yet supported.\n"); delete $2;}
| K_open
;
entity_aspect_opt
: entity_aspect
|
;
entity_declaration
: K_entity IDENTIFIER K_is entity_header K_end K_entity_opt identifier_opt';'
{ Entity*tmp = new Entity(lex_strings.make($2));
@ -348,6 +448,7 @@ entity_declaration
if($7) {
if(tmp->get_name() != $7) {
errormsg(@1, "Syntax error in entity clause. Closing name doesn't match.\n");
yyerrok;
}
delete $7;
}
@ -485,6 +586,14 @@ factor
$$ = tmp;
}
;
generic_map_aspect_opt
: generic_map_aspect
|
;
generic_map_aspect
: K_generic K_map '(' association_list ')'
;
identifier_list
: identifier_list ',' IDENTIFIER
@ -503,6 +612,20 @@ identifier_list
identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ;
instantiation_list
: identifier_list
{
sorrymsg(@1, "Instatiation lists not yet supported");
delete $1;
}
| K_others
| K_all
{
sorrymsg(@1, "Instatiation lists not yet supported");
}
;
/* The interface_element is also an interface_declaration */
interface_element
: identifier_list ':' mode subtype_indication
@ -546,8 +669,8 @@ library_clause
/* Collapse the primary_unit and secondary_unit of the library_unit
into this single set of rules. */
library_unit
: entity_declaration
| architecture_body
: primary_unit
| secondary_unit
;
logical_name : IDENTIFIER { $$ = $1; } ;
@ -587,11 +710,71 @@ name
}
;
package_declaration
: K_package IDENTIFIER K_is
package_declarative_part_opt
K_end K_package_opt identifier_opt ';'
{ sorrymsg(@4, "Package declaration not supported yet.\n");
if($7) {
if($2 != $7) {
errormsg(@1, "Syntax error in package clause. Closing name doesn't match.\n");
yyerrok;
}
delete $7;
}
delete $2;
}
| K_package error K_end K_package_opt identifier_opt ';'
{ errormsg(@2, "Syntax error in package clause.\n");
yyerrok;
}
;
/* TODO: this list must be extended in the future
presently it is only a sketch */
package_body_declarative_item
: use_clause
;
package_body_declarative_items
: package_body_declarative_items package_body_declarative_item
| package_body_declarative_item
;
package_body_declarative_part_opt
: package_body_declarative_items
|
;
/* TODO: this list is only a sketch
it must be extended in the future */
package_declarative_item
: use_clause
;
package_declarative_items
: package_declarative_items package_declarative_item
| package_declarative_item
;
package_declarative_part_opt
: package_declarative_items
|
;
package_body
: K_package K_body IDENTIFIER K_is
package_body_declarative_part_opt
K_end K_package_opt identifier_opt ';'
{
delete[] $3;
if($8) delete[] $8;
}
;
port_clause
: K_port '(' interface_list ')' ';'
{ $$ = $3; }
| K_port '(' error ')' ';'
{ errormsg(@1, "Syntax error in port list\n");
{ errormsg(@1, "Syntax error in port list.\n");
yyerrok;
$$ = 0;
}
@ -620,8 +803,18 @@ primary
{ $$ = $2; }
;
primary_unit
: entity_declaration
| configuration_declaration
| package_declaration
;
relation : shift_expression { $$ = $1; } ;
secondary_unit
: architecture_body
| package_body
;
/* The *_use variant of selected_name is used by the "use"
clause. It is syntactically identical to other selected_name
rules, but is a convenient place to attach use_clause actions. */
@ -703,6 +896,16 @@ use_clause
{ errormsg(@1, "Syntax error in use clause.\n"); yyerrok; }
;
use_clauses
: use_clauses use_clause
| use_clause
;
use_clauses_opt
: use_clauses
|
;
waveform
: waveform_elements
{ $$ = $1; }
@ -733,7 +936,9 @@ waveform_element
/* Some keywords are optional in some contexts. In all such cases, a
similar rule is used, as described here. */
K_architecture_opt : K_architecture | ;
K_configuration_opt: K_configuration| ;
K_entity_opt : K_entity | ;
K_package_opt : K_package | ;
K_is_opt : K_is | ;
%%

View File

@ -54,7 +54,7 @@ extern int yylex(void);
extern int yyparse(void);
/*
* Use this functio during parse to generate error messages. The "loc"
* Use this function during parse to generate error messages. The "loc"
* is the location of the token that triggered the error, and the fmt
* is printf-style format.
*/

View File

@ -282,7 +282,7 @@ general syntax of a variable is:
<label> .var/s "name", <msb> <lsb>; Signed logic variable
<label> .var/2u "name", <msb> <lsb>; Unsigned bool/bit variable
<label> .var/2s "name", <msb> <lsb>; Signed bool/bit variable
<label> .var/real "name", <msb>, <lsb>; real varibale
<label> .var/real "name", <msb>, <lsb>; real variable
<label> .var/i "name", <msb>, <lsb>; vpiIntegerVar variable
The "name" is the declared base name of the original variable, for the
@ -757,7 +757,7 @@ code is undefined.
* Thread Context
The context of a thread is all the local data that only that thread
can address. The local data is broken into two addresses spaces: bit
can address. The local data is broken into two address spaces: bit
memory and word memory.
The bit memory is a region of 4-value bits (0,1,x,z) that can be
@ -1109,8 +1109,8 @@ associated with that variable or event.
Each VVP thread keeps track of its current write context and current
read context. For threads executing in a static scope, these are both
initialised to null values. For threads executing in an automatically
allocated scope, these are both initialised to refer to the context
initialized to null values. For threads executing in an automatically
allocated scope, these are both initialized to refer to the context
allocated to that scope.
Before starting the copying of the input parameters of an automatic

View File

@ -40,7 +40,7 @@
permaheap vvp_net_fun_t::heap_;
permaheap vvp_net_fil_t::heap_;
// Allocate around 1Megbytes/chunk.
// Allocate around 1Megabyte/chunk.
static const size_t VVP_NET_CHUNK = 1024*1024/sizeof(vvp_net_t);
static vvp_net_t*vvp_net_alloc_table = NULL;
#ifdef CHECK_WITH_VALGRIND