2013-01-05 04:13:26 -06:00
|
|
|
/*
|
|
|
|
* yosys -- Yosys Open SYnthesis Suite
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
2015-07-02 04:14:30 -05:00
|
|
|
*
|
2013-01-05 04:13:26 -06:00
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
2015-07-02 04:14:30 -05:00
|
|
|
*
|
2013-01-05 04:13:26 -06:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*
|
|
|
|
* ---
|
|
|
|
*
|
|
|
|
* A very simple and straightforward frontend for the RTLIL text
|
|
|
|
* representation (as generated by the 'ilang' backend).
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
%{
|
|
|
|
#include <list>
|
2015-08-12 08:04:44 -05:00
|
|
|
#include "frontends/ilang/ilang_frontend.h"
|
2014-07-31 06:19:47 -05:00
|
|
|
YOSYS_NAMESPACE_BEGIN
|
2013-01-05 04:13:26 -06:00
|
|
|
namespace ILANG_FRONTEND {
|
2014-08-23 08:03:55 -05:00
|
|
|
std::istream *lexin;
|
2013-01-05 04:13:26 -06:00
|
|
|
RTLIL::Design *current_design;
|
|
|
|
RTLIL::Module *current_module;
|
|
|
|
RTLIL::Wire *current_wire;
|
|
|
|
RTLIL::Memory *current_memory;
|
|
|
|
RTLIL::Cell *current_cell;
|
|
|
|
RTLIL::Process *current_process;
|
|
|
|
std::vector<std::vector<RTLIL::SwitchRule*>*> switch_stack;
|
|
|
|
std::vector<RTLIL::CaseRule*> case_stack;
|
2014-12-26 03:53:21 -06:00
|
|
|
dict<RTLIL::IdString, RTLIL::Const> attrbuf;
|
2019-04-05 10:31:49 -05:00
|
|
|
bool flag_nooverwrite, flag_overwrite, flag_lib;
|
2018-12-23 08:45:09 -06:00
|
|
|
bool delete_current_module;
|
2013-01-05 04:13:26 -06:00
|
|
|
}
|
|
|
|
using namespace ILANG_FRONTEND;
|
2014-07-31 06:19:47 -05:00
|
|
|
YOSYS_NAMESPACE_END
|
|
|
|
USING_YOSYS_NAMESPACE
|
2013-01-05 04:13:26 -06:00
|
|
|
%}
|
|
|
|
|
2019-05-06 08:38:43 -05:00
|
|
|
%define api.prefix {rtlil_frontend_ilang_yy}
|
2013-01-05 04:13:26 -06:00
|
|
|
|
2019-05-14 23:07:26 -05:00
|
|
|
/* The union is defined in the header, so we need to provide all the
|
|
|
|
* includes it requires
|
|
|
|
*/
|
|
|
|
%code requires {
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include "frontends/ilang/ilang_frontend.h"
|
|
|
|
}
|
|
|
|
|
2013-01-05 04:13:26 -06:00
|
|
|
%union {
|
|
|
|
char *string;
|
|
|
|
int integer;
|
2014-07-31 06:19:47 -05:00
|
|
|
YOSYS_NAMESPACE_PREFIX RTLIL::Const *data;
|
|
|
|
YOSYS_NAMESPACE_PREFIX RTLIL::SigSpec *sigspec;
|
2015-11-27 12:46:47 -06:00
|
|
|
std::vector<YOSYS_NAMESPACE_PREFIX RTLIL::SigSpec> *rsigspec;
|
2013-01-05 04:13:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
%token <string> TOK_ID TOK_VALUE TOK_STRING
|
|
|
|
%token <integer> TOK_INT
|
2014-07-21 08:15:18 -05:00
|
|
|
%token TOK_AUTOIDX TOK_MODULE TOK_WIRE TOK_WIDTH TOK_INPUT TOK_OUTPUT TOK_INOUT
|
2013-01-05 04:13:26 -06:00
|
|
|
%token TOK_CELL TOK_CONNECT TOK_SWITCH TOK_CASE TOK_ASSIGN TOK_SYNC
|
2016-10-14 05:33:56 -05:00
|
|
|
%token TOK_LOW TOK_HIGH TOK_POSEDGE TOK_NEGEDGE TOK_EDGE TOK_ALWAYS TOK_GLOBAL TOK_INIT
|
2013-01-05 04:13:26 -06:00
|
|
|
%token TOK_UPDATE TOK_PROCESS TOK_END TOK_INVALID TOK_EOL TOK_OFFSET
|
2019-05-06 05:00:40 -05:00
|
|
|
%token TOK_PARAMETER TOK_ATTRIBUTE TOK_MEMORY TOK_SIZE TOK_SIGNED TOK_REAL TOK_UPTO
|
2013-01-05 04:13:26 -06:00
|
|
|
|
2015-11-27 12:46:47 -06:00
|
|
|
%type <rsigspec> sigspec_list_reversed
|
2013-01-05 04:13:26 -06:00
|
|
|
%type <sigspec> sigspec sigspec_list
|
|
|
|
%type <integer> sync_type
|
|
|
|
%type <data> constant
|
|
|
|
|
|
|
|
%expect 0
|
|
|
|
%debug
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
input:
|
|
|
|
optional_eol {
|
|
|
|
attrbuf.clear();
|
|
|
|
} design {
|
|
|
|
if (attrbuf.size() != 0)
|
|
|
|
rtlil_frontend_ilang_yyerror("dangling attribute");
|
|
|
|
};
|
|
|
|
|
2014-02-01 10:28:02 -06:00
|
|
|
EOL:
|
|
|
|
optional_eol TOK_EOL;
|
|
|
|
|
2013-01-05 04:13:26 -06:00
|
|
|
optional_eol:
|
|
|
|
optional_eol TOK_EOL | /* empty */;
|
|
|
|
|
|
|
|
design:
|
|
|
|
design module |
|
|
|
|
design attr_stmt |
|
2014-07-21 08:15:18 -05:00
|
|
|
design autoidx_stmt |
|
2013-01-05 04:13:26 -06:00
|
|
|
/* empty */;
|
|
|
|
|
|
|
|
module:
|
2014-02-01 10:28:02 -06:00
|
|
|
TOK_MODULE TOK_ID EOL {
|
2018-12-23 08:45:09 -06:00
|
|
|
delete_current_module = false;
|
|
|
|
if (current_design->has($2)) {
|
|
|
|
RTLIL::Module *existing_mod = current_design->module($2);
|
2020-05-04 12:48:37 -05:00
|
|
|
if (!flag_overwrite && (flag_lib || (attrbuf.count(ID::blackbox) && attrbuf.at(ID::blackbox).as_bool()))) {
|
2018-12-23 08:45:09 -06:00
|
|
|
log("Ignoring blackbox re-definition of module %s.\n", $2);
|
|
|
|
delete_current_module = true;
|
2020-05-04 12:48:37 -05:00
|
|
|
} else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) {
|
2018-12-23 08:45:09 -06:00
|
|
|
rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of module %s.", $2).c_str());
|
|
|
|
} else if (flag_nooverwrite) {
|
|
|
|
log("Ignoring re-definition of module %s.\n", $2);
|
|
|
|
delete_current_module = true;
|
|
|
|
} else {
|
2020-05-04 12:48:37 -05:00
|
|
|
log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "", $2);
|
2018-12-23 08:45:09 -06:00
|
|
|
current_design->remove(existing_mod);
|
|
|
|
}
|
|
|
|
}
|
2013-01-05 04:13:26 -06:00
|
|
|
current_module = new RTLIL::Module;
|
|
|
|
current_module->name = $2;
|
|
|
|
current_module->attributes = attrbuf;
|
2018-12-23 08:45:09 -06:00
|
|
|
if (!delete_current_module)
|
|
|
|
current_design->add(current_module);
|
2013-01-05 04:13:26 -06:00
|
|
|
attrbuf.clear();
|
|
|
|
free($2);
|
|
|
|
} module_body TOK_END {
|
|
|
|
if (attrbuf.size() != 0)
|
|
|
|
rtlil_frontend_ilang_yyerror("dangling attribute");
|
2014-08-14 09:13:42 -05:00
|
|
|
current_module->fixup_ports();
|
2018-12-23 08:45:09 -06:00
|
|
|
if (delete_current_module)
|
|
|
|
delete current_module;
|
2019-04-05 10:31:49 -05:00
|
|
|
else if (flag_lib)
|
|
|
|
current_module->makeblackbox();
|
2018-12-23 08:45:09 -06:00
|
|
|
current_module = nullptr;
|
2014-02-01 10:28:02 -06:00
|
|
|
} EOL;
|
2013-01-05 04:13:26 -06:00
|
|
|
|
|
|
|
module_body:
|
|
|
|
module_body module_stmt |
|
|
|
|
/* empty */;
|
|
|
|
|
|
|
|
module_stmt:
|
2020-04-16 08:51:03 -05:00
|
|
|
param_stmt | param_defval_stmt | attr_stmt | wire_stmt | memory_stmt | cell_stmt | proc_stmt | conn_stmt;
|
2016-10-22 04:05:49 -05:00
|
|
|
|
|
|
|
param_stmt:
|
|
|
|
TOK_PARAMETER TOK_ID EOL {
|
2020-04-16 08:51:03 -05:00
|
|
|
current_module->avail_parameters($2);
|
|
|
|
free($2);
|
|
|
|
};
|
|
|
|
|
|
|
|
param_defval_stmt:
|
|
|
|
TOK_PARAMETER TOK_ID constant EOL {
|
|
|
|
current_module->avail_parameters($2);
|
|
|
|
current_module->parameter_default_values[$2] = *$3;
|
2016-10-22 04:05:49 -05:00
|
|
|
free($2);
|
|
|
|
};
|
2013-01-05 04:13:26 -06:00
|
|
|
|
|
|
|
attr_stmt:
|
2014-02-01 10:28:02 -06:00
|
|
|
TOK_ATTRIBUTE TOK_ID constant EOL {
|
2013-01-05 04:13:26 -06:00
|
|
|
attrbuf[$2] = *$3;
|
|
|
|
delete $3;
|
2013-05-23 05:55:59 -05:00
|
|
|
free($2);
|
2013-01-05 04:13:26 -06:00
|
|
|
};
|
|
|
|
|
2014-07-21 08:15:18 -05:00
|
|
|
autoidx_stmt:
|
|
|
|
TOK_AUTOIDX TOK_INT EOL {
|
2015-10-25 13:30:49 -05:00
|
|
|
autoidx = max(autoidx, $2);
|
2014-07-21 08:15:18 -05:00
|
|
|
};
|
|
|
|
|
2013-01-05 04:13:26 -06:00
|
|
|
wire_stmt:
|
|
|
|
TOK_WIRE {
|
2014-07-26 13:12:50 -05:00
|
|
|
current_wire = current_module->addWire("$__ilang_frontend_tmp__");
|
2013-01-05 04:13:26 -06:00
|
|
|
current_wire->attributes = attrbuf;
|
|
|
|
attrbuf.clear();
|
2014-02-01 10:28:02 -06:00
|
|
|
} wire_options TOK_ID EOL {
|
2020-04-12 23:22:00 -05:00
|
|
|
if (current_module->wire($4) != nullptr)
|
2014-02-11 12:17:07 -06:00
|
|
|
rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of wire %s.", $4).c_str());
|
2014-07-26 13:12:50 -05:00
|
|
|
current_module->rename(current_wire, $4);
|
2013-01-05 04:13:26 -06:00
|
|
|
free($4);
|
|
|
|
};
|
|
|
|
|
|
|
|
wire_options:
|
|
|
|
wire_options TOK_WIDTH TOK_INT {
|
|
|
|
current_wire->width = $3;
|
|
|
|
} |
|
2020-04-06 05:32:50 -05:00
|
|
|
wire_options TOK_WIDTH TOK_INVALID {
|
|
|
|
rtlil_frontend_ilang_yyerror("ilang error: invalid wire width");
|
|
|
|
} |
|
2014-07-28 05:12:13 -05:00
|
|
|
wire_options TOK_UPTO {
|
|
|
|
current_wire->upto = true;
|
|
|
|
} |
|
2020-04-27 11:44:24 -05:00
|
|
|
wire_options TOK_SIGNED {
|
|
|
|
current_wire->is_signed = true;
|
|
|
|
} |
|
2013-01-05 04:13:26 -06:00
|
|
|
wire_options TOK_OFFSET TOK_INT {
|
|
|
|
current_wire->start_offset = $3;
|
|
|
|
} |
|
|
|
|
wire_options TOK_INPUT TOK_INT {
|
|
|
|
current_wire->port_id = $3;
|
|
|
|
current_wire->port_input = true;
|
|
|
|
current_wire->port_output = false;
|
|
|
|
} |
|
|
|
|
wire_options TOK_OUTPUT TOK_INT {
|
|
|
|
current_wire->port_id = $3;
|
|
|
|
current_wire->port_input = false;
|
|
|
|
current_wire->port_output = true;
|
|
|
|
} |
|
|
|
|
wire_options TOK_INOUT TOK_INT {
|
|
|
|
current_wire->port_id = $3;
|
|
|
|
current_wire->port_input = true;
|
|
|
|
current_wire->port_output = true;
|
|
|
|
} |
|
|
|
|
/* empty */;
|
|
|
|
|
|
|
|
memory_stmt:
|
|
|
|
TOK_MEMORY {
|
|
|
|
current_memory = new RTLIL::Memory;
|
|
|
|
current_memory->attributes = attrbuf;
|
|
|
|
attrbuf.clear();
|
2014-02-01 10:28:02 -06:00
|
|
|
} memory_options TOK_ID EOL {
|
2013-01-05 04:13:26 -06:00
|
|
|
if (current_module->memories.count($4) != 0)
|
2014-02-11 12:17:07 -06:00
|
|
|
rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of memory %s.", $4).c_str());
|
2013-01-05 04:13:26 -06:00
|
|
|
current_memory->name = $4;
|
|
|
|
current_module->memories[$4] = current_memory;
|
|
|
|
free($4);
|
|
|
|
};
|
|
|
|
|
|
|
|
memory_options:
|
|
|
|
memory_options TOK_WIDTH TOK_INT {
|
2013-11-20 12:55:52 -06:00
|
|
|
current_memory->width = $3;
|
2013-01-05 04:13:26 -06:00
|
|
|
} |
|
|
|
|
memory_options TOK_SIZE TOK_INT {
|
|
|
|
current_memory->size = $3;
|
|
|
|
} |
|
2015-01-01 05:56:01 -06:00
|
|
|
memory_options TOK_OFFSET TOK_INT {
|
|
|
|
current_memory->start_offset = $3;
|
|
|
|
} |
|
2013-01-05 04:13:26 -06:00
|
|
|
/* empty */;
|
|
|
|
|
|
|
|
cell_stmt:
|
2014-02-01 10:28:02 -06:00
|
|
|
TOK_CELL TOK_ID TOK_ID EOL {
|
2020-04-12 23:22:00 -05:00
|
|
|
if (current_module->cell($3) != nullptr)
|
2014-02-11 12:17:07 -06:00
|
|
|
rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell %s.", $3).c_str());
|
2014-07-25 08:05:18 -05:00
|
|
|
current_cell = current_module->addCell($3, $2);
|
2013-01-05 04:13:26 -06:00
|
|
|
current_cell->attributes = attrbuf;
|
|
|
|
attrbuf.clear();
|
|
|
|
free($2);
|
|
|
|
free($3);
|
2014-02-01 10:28:02 -06:00
|
|
|
} cell_body TOK_END EOL;
|
2013-01-05 04:13:26 -06:00
|
|
|
|
|
|
|
cell_body:
|
2014-02-01 10:28:02 -06:00
|
|
|
cell_body TOK_PARAMETER TOK_ID constant EOL {
|
2013-01-05 04:13:26 -06:00
|
|
|
current_cell->parameters[$3] = *$4;
|
|
|
|
free($3);
|
|
|
|
delete $4;
|
|
|
|
} |
|
2014-02-01 10:28:02 -06:00
|
|
|
cell_body TOK_PARAMETER TOK_SIGNED TOK_ID constant EOL {
|
2013-11-24 10:37:27 -06:00
|
|
|
current_cell->parameters[$4] = *$5;
|
2013-12-04 07:24:44 -06:00
|
|
|
current_cell->parameters[$4].flags |= RTLIL::CONST_FLAG_SIGNED;
|
2013-11-24 10:37:27 -06:00
|
|
|
free($4);
|
|
|
|
delete $5;
|
|
|
|
} |
|
2019-05-06 05:00:40 -05:00
|
|
|
cell_body TOK_PARAMETER TOK_REAL TOK_ID constant EOL {
|
|
|
|
current_cell->parameters[$4] = *$5;
|
|
|
|
current_cell->parameters[$4].flags |= RTLIL::CONST_FLAG_REAL;
|
|
|
|
free($4);
|
|
|
|
delete $5;
|
|
|
|
} |
|
2014-02-01 10:28:02 -06:00
|
|
|
cell_body TOK_CONNECT TOK_ID sigspec EOL {
|
2014-07-31 09:38:54 -05:00
|
|
|
if (current_cell->hasPort($3))
|
2014-02-11 12:17:07 -06:00
|
|
|
rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell port %s.", $3).c_str());
|
2014-07-31 09:38:54 -05:00
|
|
|
current_cell->setPort($3, *$4);
|
2013-01-05 04:13:26 -06:00
|
|
|
delete $4;
|
|
|
|
free($3);
|
|
|
|
} |
|
|
|
|
/* empty */;
|
|
|
|
|
|
|
|
proc_stmt:
|
2014-02-01 10:28:02 -06:00
|
|
|
TOK_PROCESS TOK_ID EOL {
|
2013-01-05 04:13:26 -06:00
|
|
|
if (current_module->processes.count($2) != 0)
|
2014-02-11 12:17:07 -06:00
|
|
|
rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of process %s.", $2).c_str());
|
2013-01-05 04:13:26 -06:00
|
|
|
current_process = new RTLIL::Process;
|
|
|
|
current_process->name = $2;
|
|
|
|
current_process->attributes = attrbuf;
|
|
|
|
current_module->processes[$2] = current_process;
|
|
|
|
switch_stack.clear();
|
|
|
|
switch_stack.push_back(¤t_process->root_case.switches);
|
|
|
|
case_stack.clear();
|
|
|
|
case_stack.push_back(¤t_process->root_case);
|
2014-07-22 13:35:58 -05:00
|
|
|
attrbuf.clear();
|
2013-01-05 04:13:26 -06:00
|
|
|
free($2);
|
2014-02-01 10:28:02 -06:00
|
|
|
} case_body sync_list TOK_END EOL;
|
2013-01-05 04:13:26 -06:00
|
|
|
|
|
|
|
switch_stmt:
|
Allow attributes on individual switch cases in RTLIL.
The parser changes are slightly awkward. Consider the following IL:
process $0
<point 1>
switch \foo
<point 2>
case 1'1
assign \bar \baz
<point 3>
...
case
end
end
Before this commit, attributes are valid in <point 1>, and <point 3>
iff it is immediately followed by a `switch`. (They are essentially
attached to the switch.) But, after this commit, and because switch
cases do not have an ending delimiter, <point 3> becomes ambiguous:
the attribute could attach to either the following `case`, or to
the following `switch`. This isn't expressible in LALR(1) and results
in a reduce/reduce conflict.
To address this, attributes inside processes are now valid anywhere
inside the process: in <point 1> and <point 3> a part of case body,
and in <point 2> as a separate rule. As a consequence, attributes
can now precede `assign`s, which is made illegal in the same way it
is illegal to attach attributes to `connect`.
Attributes are tracked separately from the parser state, so this
does not affect collection of attributes at all, other than allowing
them on `case`s. The grammar change serves purely to allow attributes
in more syntactic places.
2019-07-08 06:34:58 -05:00
|
|
|
TOK_SWITCH sigspec EOL {
|
2013-01-05 04:13:26 -06:00
|
|
|
RTLIL::SwitchRule *rule = new RTLIL::SwitchRule;
|
Allow attributes on individual switch cases in RTLIL.
The parser changes are slightly awkward. Consider the following IL:
process $0
<point 1>
switch \foo
<point 2>
case 1'1
assign \bar \baz
<point 3>
...
case
end
end
Before this commit, attributes are valid in <point 1>, and <point 3>
iff it is immediately followed by a `switch`. (They are essentially
attached to the switch.) But, after this commit, and because switch
cases do not have an ending delimiter, <point 3> becomes ambiguous:
the attribute could attach to either the following `case`, or to
the following `switch`. This isn't expressible in LALR(1) and results
in a reduce/reduce conflict.
To address this, attributes inside processes are now valid anywhere
inside the process: in <point 1> and <point 3> a part of case body,
and in <point 2> as a separate rule. As a consequence, attributes
can now precede `assign`s, which is made illegal in the same way it
is illegal to attach attributes to `connect`.
Attributes are tracked separately from the parser state, so this
does not affect collection of attributes at all, other than allowing
them on `case`s. The grammar change serves purely to allow attributes
in more syntactic places.
2019-07-08 06:34:58 -05:00
|
|
|
rule->signal = *$2;
|
2013-01-05 04:13:26 -06:00
|
|
|
rule->attributes = attrbuf;
|
|
|
|
switch_stack.back()->push_back(rule);
|
|
|
|
attrbuf.clear();
|
Allow attributes on individual switch cases in RTLIL.
The parser changes are slightly awkward. Consider the following IL:
process $0
<point 1>
switch \foo
<point 2>
case 1'1
assign \bar \baz
<point 3>
...
case
end
end
Before this commit, attributes are valid in <point 1>, and <point 3>
iff it is immediately followed by a `switch`. (They are essentially
attached to the switch.) But, after this commit, and because switch
cases do not have an ending delimiter, <point 3> becomes ambiguous:
the attribute could attach to either the following `case`, or to
the following `switch`. This isn't expressible in LALR(1) and results
in a reduce/reduce conflict.
To address this, attributes inside processes are now valid anywhere
inside the process: in <point 1> and <point 3> a part of case body,
and in <point 2> as a separate rule. As a consequence, attributes
can now precede `assign`s, which is made illegal in the same way it
is illegal to attach attributes to `connect`.
Attributes are tracked separately from the parser state, so this
does not affect collection of attributes at all, other than allowing
them on `case`s. The grammar change serves purely to allow attributes
in more syntactic places.
2019-07-08 06:34:58 -05:00
|
|
|
delete $2;
|
|
|
|
} attr_list switch_body TOK_END EOL;
|
2013-01-05 04:13:26 -06:00
|
|
|
|
|
|
|
attr_list:
|
|
|
|
/* empty */ |
|
|
|
|
attr_list attr_stmt;
|
|
|
|
|
|
|
|
switch_body:
|
|
|
|
switch_body TOK_CASE {
|
|
|
|
RTLIL::CaseRule *rule = new RTLIL::CaseRule;
|
Allow attributes on individual switch cases in RTLIL.
The parser changes are slightly awkward. Consider the following IL:
process $0
<point 1>
switch \foo
<point 2>
case 1'1
assign \bar \baz
<point 3>
...
case
end
end
Before this commit, attributes are valid in <point 1>, and <point 3>
iff it is immediately followed by a `switch`. (They are essentially
attached to the switch.) But, after this commit, and because switch
cases do not have an ending delimiter, <point 3> becomes ambiguous:
the attribute could attach to either the following `case`, or to
the following `switch`. This isn't expressible in LALR(1) and results
in a reduce/reduce conflict.
To address this, attributes inside processes are now valid anywhere
inside the process: in <point 1> and <point 3> a part of case body,
and in <point 2> as a separate rule. As a consequence, attributes
can now precede `assign`s, which is made illegal in the same way it
is illegal to attach attributes to `connect`.
Attributes are tracked separately from the parser state, so this
does not affect collection of attributes at all, other than allowing
them on `case`s. The grammar change serves purely to allow attributes
in more syntactic places.
2019-07-08 06:34:58 -05:00
|
|
|
rule->attributes = attrbuf;
|
2013-01-05 04:13:26 -06:00
|
|
|
switch_stack.back()->back()->cases.push_back(rule);
|
|
|
|
switch_stack.push_back(&rule->switches);
|
|
|
|
case_stack.push_back(rule);
|
Allow attributes on individual switch cases in RTLIL.
The parser changes are slightly awkward. Consider the following IL:
process $0
<point 1>
switch \foo
<point 2>
case 1'1
assign \bar \baz
<point 3>
...
case
end
end
Before this commit, attributes are valid in <point 1>, and <point 3>
iff it is immediately followed by a `switch`. (They are essentially
attached to the switch.) But, after this commit, and because switch
cases do not have an ending delimiter, <point 3> becomes ambiguous:
the attribute could attach to either the following `case`, or to
the following `switch`. This isn't expressible in LALR(1) and results
in a reduce/reduce conflict.
To address this, attributes inside processes are now valid anywhere
inside the process: in <point 1> and <point 3> a part of case body,
and in <point 2> as a separate rule. As a consequence, attributes
can now precede `assign`s, which is made illegal in the same way it
is illegal to attach attributes to `connect`.
Attributes are tracked separately from the parser state, so this
does not affect collection of attributes at all, other than allowing
them on `case`s. The grammar change serves purely to allow attributes
in more syntactic places.
2019-07-08 06:34:58 -05:00
|
|
|
attrbuf.clear();
|
2014-02-01 10:28:02 -06:00
|
|
|
} compare_list EOL case_body {
|
2013-01-05 04:13:26 -06:00
|
|
|
switch_stack.pop_back();
|
|
|
|
case_stack.pop_back();
|
|
|
|
} |
|
|
|
|
/* empty */;
|
|
|
|
|
|
|
|
compare_list:
|
|
|
|
sigspec {
|
|
|
|
case_stack.back()->compare.push_back(*$1);
|
|
|
|
delete $1;
|
|
|
|
} |
|
|
|
|
compare_list ',' sigspec {
|
|
|
|
case_stack.back()->compare.push_back(*$3);
|
|
|
|
delete $3;
|
|
|
|
} |
|
|
|
|
/* empty */;
|
|
|
|
|
|
|
|
case_body:
|
Allow attributes on individual switch cases in RTLIL.
The parser changes are slightly awkward. Consider the following IL:
process $0
<point 1>
switch \foo
<point 2>
case 1'1
assign \bar \baz
<point 3>
...
case
end
end
Before this commit, attributes are valid in <point 1>, and <point 3>
iff it is immediately followed by a `switch`. (They are essentially
attached to the switch.) But, after this commit, and because switch
cases do not have an ending delimiter, <point 3> becomes ambiguous:
the attribute could attach to either the following `case`, or to
the following `switch`. This isn't expressible in LALR(1) and results
in a reduce/reduce conflict.
To address this, attributes inside processes are now valid anywhere
inside the process: in <point 1> and <point 3> a part of case body,
and in <point 2> as a separate rule. As a consequence, attributes
can now precede `assign`s, which is made illegal in the same way it
is illegal to attach attributes to `connect`.
Attributes are tracked separately from the parser state, so this
does not affect collection of attributes at all, other than allowing
them on `case`s. The grammar change serves purely to allow attributes
in more syntactic places.
2019-07-08 06:34:58 -05:00
|
|
|
case_body attr_stmt |
|
2015-11-29 13:30:32 -06:00
|
|
|
case_body switch_stmt |
|
|
|
|
case_body assign_stmt |
|
2013-01-05 04:13:26 -06:00
|
|
|
/* empty */;
|
|
|
|
|
|
|
|
assign_stmt:
|
2014-02-01 10:28:02 -06:00
|
|
|
TOK_ASSIGN sigspec sigspec EOL {
|
Allow attributes on individual switch cases in RTLIL.
The parser changes are slightly awkward. Consider the following IL:
process $0
<point 1>
switch \foo
<point 2>
case 1'1
assign \bar \baz
<point 3>
...
case
end
end
Before this commit, attributes are valid in <point 1>, and <point 3>
iff it is immediately followed by a `switch`. (They are essentially
attached to the switch.) But, after this commit, and because switch
cases do not have an ending delimiter, <point 3> becomes ambiguous:
the attribute could attach to either the following `case`, or to
the following `switch`. This isn't expressible in LALR(1) and results
in a reduce/reduce conflict.
To address this, attributes inside processes are now valid anywhere
inside the process: in <point 1> and <point 3> a part of case body,
and in <point 2> as a separate rule. As a consequence, attributes
can now precede `assign`s, which is made illegal in the same way it
is illegal to attach attributes to `connect`.
Attributes are tracked separately from the parser state, so this
does not affect collection of attributes at all, other than allowing
them on `case`s. The grammar change serves purely to allow attributes
in more syntactic places.
2019-07-08 06:34:58 -05:00
|
|
|
if (attrbuf.size() != 0)
|
|
|
|
rtlil_frontend_ilang_yyerror("dangling attribute");
|
2013-01-05 04:13:26 -06:00
|
|
|
case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3));
|
|
|
|
delete $2;
|
|
|
|
delete $3;
|
|
|
|
};
|
|
|
|
|
|
|
|
sync_list:
|
2014-02-01 10:28:02 -06:00
|
|
|
sync_list TOK_SYNC sync_type sigspec EOL {
|
2013-01-05 04:13:26 -06:00
|
|
|
RTLIL::SyncRule *rule = new RTLIL::SyncRule;
|
|
|
|
rule->type = RTLIL::SyncType($3);
|
|
|
|
rule->signal = *$4;
|
|
|
|
current_process->syncs.push_back(rule);
|
|
|
|
delete $4;
|
|
|
|
} update_list |
|
2014-02-01 10:28:02 -06:00
|
|
|
sync_list TOK_SYNC TOK_ALWAYS EOL {
|
2013-01-05 04:13:26 -06:00
|
|
|
RTLIL::SyncRule *rule = new RTLIL::SyncRule;
|
|
|
|
rule->type = RTLIL::SyncType::STa;
|
|
|
|
rule->signal = RTLIL::SigSpec();
|
|
|
|
current_process->syncs.push_back(rule);
|
|
|
|
} update_list |
|
2016-10-14 05:33:56 -05:00
|
|
|
sync_list TOK_SYNC TOK_GLOBAL EOL {
|
|
|
|
RTLIL::SyncRule *rule = new RTLIL::SyncRule;
|
|
|
|
rule->type = RTLIL::SyncType::STg;
|
|
|
|
rule->signal = RTLIL::SigSpec();
|
|
|
|
current_process->syncs.push_back(rule);
|
|
|
|
} update_list |
|
2014-02-01 10:28:02 -06:00
|
|
|
sync_list TOK_SYNC TOK_INIT EOL {
|
2013-11-21 06:49:00 -06:00
|
|
|
RTLIL::SyncRule *rule = new RTLIL::SyncRule;
|
|
|
|
rule->type = RTLIL::SyncType::STi;
|
|
|
|
rule->signal = RTLIL::SigSpec();
|
|
|
|
current_process->syncs.push_back(rule);
|
|
|
|
} update_list |
|
2013-01-05 04:13:26 -06:00
|
|
|
/* empty */;
|
|
|
|
|
|
|
|
sync_type:
|
|
|
|
TOK_LOW { $$ = RTLIL::ST0; } |
|
|
|
|
TOK_HIGH { $$ = RTLIL::ST1; } |
|
|
|
|
TOK_POSEDGE { $$ = RTLIL::STp; } |
|
|
|
|
TOK_NEGEDGE { $$ = RTLIL::STn; } |
|
|
|
|
TOK_EDGE { $$ = RTLIL::STe; };
|
|
|
|
|
|
|
|
update_list:
|
2014-02-01 10:28:02 -06:00
|
|
|
update_list TOK_UPDATE sigspec sigspec EOL {
|
2013-01-05 04:13:26 -06:00
|
|
|
current_process->syncs.back()->actions.push_back(RTLIL::SigSig(*$3, *$4));
|
|
|
|
delete $3;
|
|
|
|
delete $4;
|
|
|
|
} |
|
|
|
|
/* empty */;
|
|
|
|
|
|
|
|
constant:
|
|
|
|
TOK_VALUE {
|
|
|
|
char *ep;
|
|
|
|
int width = strtol($1, &ep, 10);
|
|
|
|
std::list<RTLIL::State> bits;
|
|
|
|
while (*(++ep) != 0) {
|
|
|
|
RTLIL::State bit = RTLIL::Sx;
|
|
|
|
switch (*ep) {
|
|
|
|
case '0': bit = RTLIL::S0; break;
|
|
|
|
case '1': bit = RTLIL::S1; break;
|
|
|
|
case 'x': bit = RTLIL::Sx; break;
|
|
|
|
case 'z': bit = RTLIL::Sz; break;
|
|
|
|
case '-': bit = RTLIL::Sa; break;
|
|
|
|
case 'm': bit = RTLIL::Sm; break;
|
|
|
|
}
|
|
|
|
bits.push_front(bit);
|
|
|
|
}
|
|
|
|
if (bits.size() == 0)
|
|
|
|
bits.push_back(RTLIL::Sx);
|
|
|
|
while ((int)bits.size() < width) {
|
|
|
|
RTLIL::State bit = bits.back();
|
|
|
|
if (bit == RTLIL::S1)
|
|
|
|
bit = RTLIL::S0;
|
|
|
|
bits.push_back(bit);
|
|
|
|
}
|
|
|
|
while ((int)bits.size() > width)
|
|
|
|
bits.pop_back();
|
|
|
|
$$ = new RTLIL::Const;
|
|
|
|
for (auto it = bits.begin(); it != bits.end(); it++)
|
|
|
|
$$->bits.push_back(*it);
|
|
|
|
free($1);
|
|
|
|
} |
|
|
|
|
TOK_INT {
|
|
|
|
$$ = new RTLIL::Const($1, 32);
|
|
|
|
} |
|
|
|
|
TOK_STRING {
|
|
|
|
$$ = new RTLIL::Const($1);
|
|
|
|
free($1);
|
|
|
|
};
|
|
|
|
|
|
|
|
sigspec:
|
|
|
|
constant {
|
2014-07-22 13:39:13 -05:00
|
|
|
$$ = new RTLIL::SigSpec(*$1);
|
2013-01-05 04:13:26 -06:00
|
|
|
delete $1;
|
|
|
|
} |
|
|
|
|
TOK_ID {
|
2020-04-12 23:22:00 -05:00
|
|
|
if (current_module->wire($1) == nullptr)
|
2014-02-11 12:17:07 -06:00
|
|
|
rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str());
|
2020-04-12 23:22:00 -05:00
|
|
|
$$ = new RTLIL::SigSpec(current_module->wire($1));
|
2013-01-05 04:13:26 -06:00
|
|
|
free($1);
|
|
|
|
} |
|
2018-12-16 11:50:36 -06:00
|
|
|
sigspec '[' TOK_INT ']' {
|
2019-11-27 15:24:39 -06:00
|
|
|
if ($3 >= $1->size() || $3 < 0)
|
|
|
|
rtlil_frontend_ilang_yyerror("bit index out of range");
|
2018-12-16 11:50:36 -06:00
|
|
|
$$ = new RTLIL::SigSpec($1->extract($3));
|
|
|
|
delete $1;
|
2013-01-05 04:13:26 -06:00
|
|
|
} |
|
2018-12-16 11:50:36 -06:00
|
|
|
sigspec '[' TOK_INT ':' TOK_INT ']' {
|
2019-11-27 15:24:39 -06:00
|
|
|
if ($3 >= $1->size() || $3 < 0 || $3 < $5)
|
|
|
|
rtlil_frontend_ilang_yyerror("invalid slice");
|
2018-12-16 11:50:36 -06:00
|
|
|
$$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1));
|
|
|
|
delete $1;
|
2013-01-05 04:13:26 -06:00
|
|
|
} |
|
|
|
|
'{' sigspec_list '}' {
|
|
|
|
$$ = $2;
|
|
|
|
};
|
|
|
|
|
2015-11-27 12:46:47 -06:00
|
|
|
sigspec_list_reversed:
|
|
|
|
sigspec_list_reversed sigspec {
|
|
|
|
$$->push_back(*$2);
|
2013-01-05 04:13:26 -06:00
|
|
|
delete $2;
|
|
|
|
} |
|
|
|
|
/* empty */ {
|
2015-11-27 12:46:47 -06:00
|
|
|
$$ = new std::vector<RTLIL::SigSpec>;
|
|
|
|
};
|
|
|
|
|
|
|
|
sigspec_list: sigspec_list_reversed {
|
2013-01-05 04:13:26 -06:00
|
|
|
$$ = new RTLIL::SigSpec;
|
2015-11-27 12:46:47 -06:00
|
|
|
for (auto it = $1->rbegin(); it != $1->rend(); it++)
|
|
|
|
$$->append(*it);
|
|
|
|
delete $1;
|
2013-01-05 04:13:26 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
conn_stmt:
|
2014-02-01 10:28:02 -06:00
|
|
|
TOK_CONNECT sigspec sigspec EOL {
|
2013-01-05 04:13:26 -06:00
|
|
|
if (attrbuf.size() != 0)
|
|
|
|
rtlil_frontend_ilang_yyerror("dangling attribute");
|
2014-07-26 04:58:03 -05:00
|
|
|
current_module->connect(*$2, *$3);
|
2013-01-05 04:13:26 -06:00
|
|
|
delete $2;
|
|
|
|
delete $3;
|
|
|
|
};
|