mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-27 02:45:52 +00:00
Merge remote-tracking branch 'origin/master' into xaig
This commit is contained in:
commit
f7a9769c14
140 changed files with 4698 additions and 1852 deletions
File diff suppressed because it is too large
Load diff
|
@ -37,16 +37,20 @@ struct AigerReader
|
|||
unsigned M, I, L, O, A;
|
||||
unsigned B, C, J, F; // Optional in AIGER 1.9
|
||||
unsigned line_count;
|
||||
uint32_t piNum, flopNum;
|
||||
|
||||
std::vector<RTLIL::Wire*> inputs;
|
||||
std::vector<RTLIL::Wire*> latches;
|
||||
std::vector<RTLIL::Wire*> outputs;
|
||||
std::vector<RTLIL::Wire*> bad_properties;
|
||||
std::vector<RTLIL::Cell*> boxes;
|
||||
|
||||
AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports);
|
||||
void parse_aiger();
|
||||
void parse_xaiger();
|
||||
void parse_aiger_ascii();
|
||||
void parse_aiger_binary();
|
||||
void post_process();
|
||||
};
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
|
|
@ -154,6 +154,7 @@ std::string AST::type2str(AstNodeType type)
|
|||
X(AST_GENIF)
|
||||
X(AST_GENCASE)
|
||||
X(AST_GENBLOCK)
|
||||
X(AST_TECALL)
|
||||
X(AST_POSEDGE)
|
||||
X(AST_NEGEDGE)
|
||||
X(AST_EDGE)
|
||||
|
@ -194,6 +195,9 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
|
|||
is_logic = false;
|
||||
is_signed = false;
|
||||
is_string = false;
|
||||
is_wand = false;
|
||||
is_wor = false;
|
||||
is_unsized = false;
|
||||
was_checked = false;
|
||||
range_valid = false;
|
||||
range_swapped = false;
|
||||
|
@ -722,7 +726,7 @@ AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
|
|||
}
|
||||
|
||||
// create an AST node for a constant (using a bit vector as value)
|
||||
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
|
||||
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized)
|
||||
{
|
||||
AstNode *node = new AstNode(AST_CONSTANT);
|
||||
node->is_signed = is_signed;
|
||||
|
@ -736,9 +740,15 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
|
|||
node->range_valid = true;
|
||||
node->range_left = node->bits.size()-1;
|
||||
node->range_right = 0;
|
||||
node->is_unsized = is_unsized;
|
||||
return node;
|
||||
}
|
||||
|
||||
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
|
||||
{
|
||||
return mkconst_bits(v, is_signed, false);
|
||||
}
|
||||
|
||||
// create an AST node for a constant (using a string in bit vector form as value)
|
||||
AstNode *AstNode::mkconst_str(const std::vector<RTLIL::State> &v)
|
||||
{
|
||||
|
@ -775,6 +785,14 @@ bool AstNode::bits_only_01() const
|
|||
return true;
|
||||
}
|
||||
|
||||
RTLIL::Const AstNode::bitsAsUnsizedConst(int width)
|
||||
{
|
||||
RTLIL::State extbit = bits.back();
|
||||
while (width > int(bits.size()))
|
||||
bits.push_back(extbit);
|
||||
return RTLIL::Const(bits);
|
||||
}
|
||||
|
||||
RTLIL::Const AstNode::bitsAsConst(int width, bool is_signed)
|
||||
{
|
||||
std::vector<RTLIL::State> bits = this->bits;
|
||||
|
@ -951,6 +969,9 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
|
|||
continue;
|
||||
if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM)
|
||||
continue;
|
||||
if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE &&
|
||||
(child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule"))
|
||||
continue;
|
||||
blackbox_module = false;
|
||||
break;
|
||||
}
|
||||
|
@ -1035,6 +1056,9 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
|
|||
child->delete_children();
|
||||
child->children.push_back(AstNode::mkconst_int(0, false, 0));
|
||||
new_children.push_back(child);
|
||||
} else if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE &&
|
||||
(child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule")) {
|
||||
new_children.push_back(child);
|
||||
} else {
|
||||
delete child;
|
||||
}
|
||||
|
|
|
@ -137,7 +137,8 @@ namespace AST
|
|||
AST_GENIF,
|
||||
AST_GENCASE,
|
||||
AST_GENBLOCK,
|
||||
|
||||
AST_TECALL,
|
||||
|
||||
AST_POSEDGE,
|
||||
AST_NEGEDGE,
|
||||
AST_EDGE,
|
||||
|
@ -173,7 +174,7 @@ namespace AST
|
|||
// node content - most of it is unused in most node types
|
||||
std::string str;
|
||||
std::vector<RTLIL::State> bits;
|
||||
bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped, was_checked;
|
||||
bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized;
|
||||
int port_id, range_left, range_right;
|
||||
uint32_t integer;
|
||||
double realvalue;
|
||||
|
@ -262,6 +263,7 @@ namespace AST
|
|||
|
||||
// helper functions for creating AST nodes for constants
|
||||
static AstNode *mkconst_int(uint32_t v, bool is_signed, int width = 32);
|
||||
static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized);
|
||||
static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed);
|
||||
static AstNode *mkconst_str(const std::vector<RTLIL::State> &v);
|
||||
static AstNode *mkconst_str(const std::string &str);
|
||||
|
@ -269,6 +271,7 @@ namespace AST
|
|||
// helper function for creating sign-extended const objects
|
||||
RTLIL::Const bitsAsConst(int width, bool is_signed);
|
||||
RTLIL::Const bitsAsConst(int width = -1);
|
||||
RTLIL::Const bitsAsUnsizedConst(int width);
|
||||
RTLIL::Const asAttrConst();
|
||||
RTLIL::Const asParaConst();
|
||||
uint64_t asInt(bool is_signed);
|
||||
|
|
|
@ -645,6 +645,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
if (!id_ast->children[0]->range_valid)
|
||||
log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", str.c_str());
|
||||
this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
|
||||
if (children.size() > 1)
|
||||
range = children[1];
|
||||
} else
|
||||
log_file_error(filename, linenum, "Failed to detect width for identifier %s!\n", str.c_str());
|
||||
if (range) {
|
||||
|
@ -902,7 +904,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
if (!range_valid)
|
||||
log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", str.c_str());
|
||||
|
||||
log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
|
||||
if (!(range_left >= range_right || (range_left == -1 && range_right == 0)))
|
||||
log_file_error(filename, linenum, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1);
|
||||
|
||||
RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1);
|
||||
wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
||||
|
@ -917,6 +920,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
wire->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
|
||||
if (is_wand) wire->set_bool_attribute("\\wand");
|
||||
if (is_wor) wire->set_bool_attribute("\\wor");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -961,8 +967,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
detectSignWidth(width_hint, sign_hint);
|
||||
is_signed = sign_hint;
|
||||
|
||||
if (type == AST_CONSTANT)
|
||||
return RTLIL::SigSpec(bitsAsConst());
|
||||
if (type == AST_CONSTANT) {
|
||||
if (is_unsized) {
|
||||
return RTLIL::SigSpec(bitsAsUnsizedConst(width_hint));
|
||||
} else {
|
||||
return RTLIL::SigSpec(bitsAsConst());
|
||||
}
|
||||
}
|
||||
|
||||
RTLIL::SigSpec sig = realAsConst(width_hint);
|
||||
log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
|
||||
|
@ -1490,10 +1501,12 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
continue;
|
||||
}
|
||||
if (child->type == AST_PARASET) {
|
||||
int extra_const_flags = 0;
|
||||
IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
|
||||
if (child->children[0]->type == AST_REALVALUE) {
|
||||
log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n",
|
||||
log_id(cell), log_id(paraname), child->children[0]->realvalue);
|
||||
extra_const_flags = RTLIL::CONST_FLAG_REAL;
|
||||
auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue));
|
||||
strnode->cloneInto(child->children[0]);
|
||||
delete strnode;
|
||||
|
@ -1502,6 +1515,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n",
|
||||
log_id(cell), log_id(paraname));
|
||||
cell->parameters[paraname] = child->children[0]->asParaConst();
|
||||
cell->parameters[paraname].flags |= extra_const_flags;
|
||||
continue;
|
||||
}
|
||||
if (child->type == AST_ARGUMENT) {
|
||||
|
@ -1521,9 +1535,29 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
}
|
||||
for (auto &attr : attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value.\n", attr.first.c_str());
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
if (cell->type.in("$specify2", "$specify3")) {
|
||||
int src_width = GetSize(cell->getPort("\\SRC"));
|
||||
int dst_width = GetSize(cell->getPort("\\DST"));
|
||||
bool full = cell->getParam("\\FULL").as_bool();
|
||||
if (!full && src_width != dst_width)
|
||||
log_file_error(filename, linenum, "Parallel specify SRC width does not match DST width.\n");
|
||||
if (cell->type == "$specify3") {
|
||||
int dat_width = GetSize(cell->getPort("\\DAT"));
|
||||
if (dat_width != dst_width)
|
||||
log_file_error(filename, linenum, "Specify DAT width does not match DST width.\n");
|
||||
}
|
||||
cell->setParam("\\SRC_WIDTH", Const(src_width));
|
||||
cell->setParam("\\DST_WIDTH", Const(dst_width));
|
||||
}
|
||||
if (cell->type == "$specrule") {
|
||||
int src_width = GetSize(cell->getPort("\\SRC"));
|
||||
int dst_width = GetSize(cell->getPort("\\DST"));
|
||||
cell->setParam("\\SRC_WIDTH", Const(src_width));
|
||||
cell->setParam("\\DST_WIDTH", Const(dst_width));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1541,6 +1575,37 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
delete always;
|
||||
} break;
|
||||
|
||||
case AST_TECALL: {
|
||||
int sz = children.size();
|
||||
if (str == "$info") {
|
||||
if (sz > 0)
|
||||
log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str());
|
||||
else
|
||||
log_file_info(filename, linenum, "\n");
|
||||
} else if (str == "$warning") {
|
||||
if (sz > 0)
|
||||
log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str());
|
||||
else
|
||||
log_file_warning(filename, linenum, "\n");
|
||||
} else if (str == "$error") {
|
||||
if (sz > 0)
|
||||
log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str());
|
||||
else
|
||||
log_file_error(filename, linenum, "\n");
|
||||
} else if (str == "$fatal") {
|
||||
// TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish()
|
||||
// if no parameter is given, default value is 1
|
||||
// dollar_finish(sz ? children[0] : 1);
|
||||
// perhaps create & use log_file_fatal()
|
||||
if (sz > 0)
|
||||
log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str());
|
||||
else
|
||||
log_file_error(filename, linenum, "FATAL.\n");
|
||||
} else {
|
||||
log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str());
|
||||
}
|
||||
} break;
|
||||
|
||||
case AST_FCALL: {
|
||||
if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq")
|
||||
{
|
||||
|
|
|
@ -1172,6 +1172,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
varbuf->children[0] = buf;
|
||||
}
|
||||
|
||||
if (type == AST_FOR) {
|
||||
AstNode *buf = next_ast->clone();
|
||||
delete buf->children[1];
|
||||
buf->children[1] = varbuf->children[0]->clone();
|
||||
current_block->children.insert(current_block->children.begin() + current_block_idx++, buf);
|
||||
}
|
||||
|
||||
current_scope[varbuf->str] = backup_scope_varbuf;
|
||||
delete varbuf;
|
||||
delete_children();
|
||||
|
@ -1598,6 +1605,7 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
current_scope[wire_tmp->str] = wire_tmp;
|
||||
wire_tmp->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||
while (wire_tmp->simplify(true, false, false, 1, -1, false, false)) { }
|
||||
wire_tmp->is_logic = true;
|
||||
|
||||
AstNode *wire_tmp_id = new AstNode(AST_IDENTIFIER);
|
||||
wire_tmp_id->str = wire_tmp->str;
|
||||
|
|
|
@ -53,6 +53,7 @@ USING_YOSYS_NAMESPACE
|
|||
"attribute" { return TOK_ATTRIBUTE; }
|
||||
"parameter" { return TOK_PARAMETER; }
|
||||
"signed" { return TOK_SIGNED; }
|
||||
"real" { return TOK_REAL; }
|
||||
"wire" { return TOK_WIRE; }
|
||||
"memory" { return TOK_MEMORY; }
|
||||
"width" { return TOK_WIDTH; }
|
||||
|
|
|
@ -45,7 +45,16 @@ YOSYS_NAMESPACE_END
|
|||
USING_YOSYS_NAMESPACE
|
||||
%}
|
||||
|
||||
%name-prefix "rtlil_frontend_ilang_yy"
|
||||
%define api.prefix {rtlil_frontend_ilang_yy}
|
||||
|
||||
/* 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"
|
||||
}
|
||||
|
||||
%union {
|
||||
char *string;
|
||||
|
@ -61,7 +70,7 @@ USING_YOSYS_NAMESPACE
|
|||
%token TOK_CELL TOK_CONNECT TOK_SWITCH TOK_CASE TOK_ASSIGN TOK_SYNC
|
||||
%token TOK_LOW TOK_HIGH TOK_POSEDGE TOK_NEGEDGE TOK_EDGE TOK_ALWAYS TOK_GLOBAL TOK_INIT
|
||||
%token TOK_UPDATE TOK_PROCESS TOK_END TOK_INVALID TOK_EOL TOK_OFFSET
|
||||
%token TOK_PARAMETER TOK_ATTRIBUTE TOK_MEMORY TOK_SIZE TOK_SIGNED TOK_UPTO
|
||||
%token TOK_PARAMETER TOK_ATTRIBUTE TOK_MEMORY TOK_SIZE TOK_SIGNED TOK_REAL TOK_UPTO
|
||||
|
||||
%type <rsigspec> sigspec_list_reversed
|
||||
%type <sigspec> sigspec sigspec_list
|
||||
|
@ -241,6 +250,12 @@ cell_body:
|
|||
free($4);
|
||||
delete $5;
|
||||
} |
|
||||
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;
|
||||
} |
|
||||
cell_body TOK_CONNECT TOK_ID sigspec EOL {
|
||||
if (current_cell->hasPort($3))
|
||||
rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell port %s.", $3).c_str());
|
||||
|
@ -445,4 +460,3 @@ conn_stmt:
|
|||
delete $2;
|
||||
delete $3;
|
||||
};
|
||||
|
||||
|
|
|
@ -46,7 +46,15 @@ USING_YOSYS_NAMESPACE
|
|||
#include "VeriModule.h"
|
||||
#include "VeriWrite.h"
|
||||
#include "VhdlUnits.h"
|
||||
#include "Message.h"
|
||||
#include "VeriLibrary.h"
|
||||
|
||||
#ifndef SYMBIOTIC_VERIFIC_API_VERSION
|
||||
# error "Only Symbiotic EDA flavored Verific is supported. Please contact office@symbioticeda.com for commercial support for Yosys+Verific."
|
||||
#endif
|
||||
|
||||
#if SYMBIOTIC_VERIFIC_API_VERSION < 1
|
||||
# error "Please update your version of Symbiotic EDA flavored Verific."
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
|
@ -776,13 +784,14 @@ void VerificImporter::merge_past_ffs(pool<RTLIL::Cell*> &candidates)
|
|||
|
||||
void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*> &nl_todo)
|
||||
{
|
||||
std::string module_name = nl->IsOperator() ? std::string("$verific$") + nl->Owner()->Name() : RTLIL::escape_id(nl->Owner()->Name());
|
||||
std::string netlist_name = nl->GetAtt(" \\top") ? nl->CellBaseName() : nl->Owner()->Name();
|
||||
std::string module_name = nl->IsOperator() ? "$verific$" + netlist_name : RTLIL::escape_id(netlist_name);
|
||||
|
||||
netlist = nl;
|
||||
|
||||
if (design->has(module_name)) {
|
||||
if (!nl->IsOperator() && !is_blackbox(nl))
|
||||
log_cmd_error("Re-definition of module `%s'.\n", nl->Owner()->Name());
|
||||
log_cmd_error("Re-definition of module `%s'.\n", netlist_name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1752,32 +1761,64 @@ struct VerificExtNets
|
|||
}
|
||||
};
|
||||
|
||||
void verific_import(Design *design, std::string top)
|
||||
void verific_import(Design *design, const std::map<std::string,std::string> ¶meters, std::string top)
|
||||
{
|
||||
verific_sva_fsm_limit = 16;
|
||||
|
||||
std::set<Netlist*> nl_todo, nl_done;
|
||||
|
||||
{
|
||||
VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary("work", 1);
|
||||
VeriLibrary *veri_lib = veri_file::GetLibrary("work", 1);
|
||||
VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary("work", 1);
|
||||
VeriLibrary *veri_lib = veri_file::GetLibrary("work", 1);
|
||||
Array *netlists = NULL;
|
||||
Array veri_libs, vhdl_libs;
|
||||
if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib);
|
||||
if (veri_lib) veri_libs.InsertLast(veri_lib);
|
||||
|
||||
Array veri_libs, vhdl_libs;
|
||||
if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib);
|
||||
if (veri_lib) veri_libs.InsertLast(veri_lib);
|
||||
Map verific_params(STRING_HASH);
|
||||
for (const auto &i : parameters)
|
||||
verific_params.Insert(i.first.c_str(), i.second.c_str());
|
||||
|
||||
Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs);
|
||||
Netlist *nl;
|
||||
int i;
|
||||
if (top.empty()) {
|
||||
netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs, &verific_params);
|
||||
}
|
||||
else {
|
||||
Array veri_modules, vhdl_units;
|
||||
|
||||
FOREACH_ARRAY_ITEM(netlists, i, nl) {
|
||||
if (top.empty() || nl->Owner()->Name() == top)
|
||||
nl_todo.insert(nl);
|
||||
if (veri_lib) {
|
||||
VeriModule *veri_module = veri_lib->GetModule(top.c_str(), 1);
|
||||
if (veri_module) {
|
||||
veri_modules.InsertLast(veri_module);
|
||||
}
|
||||
|
||||
// Also elaborate all root modules since they may contain bind statements
|
||||
MapIter mi;
|
||||
FOREACH_VERILOG_MODULE_IN_LIBRARY(veri_lib, mi, veri_module) {
|
||||
if (!veri_module->IsRootModule()) continue;
|
||||
veri_modules.InsertLast(veri_module);
|
||||
}
|
||||
}
|
||||
|
||||
delete netlists;
|
||||
if (vhdl_lib) {
|
||||
VhdlDesignUnit *vhdl_unit = vhdl_lib->GetPrimUnit(top.c_str());
|
||||
if (vhdl_unit)
|
||||
vhdl_units.InsertLast(vhdl_unit);
|
||||
}
|
||||
|
||||
netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units, &verific_params);
|
||||
}
|
||||
|
||||
Netlist *nl;
|
||||
int i;
|
||||
|
||||
FOREACH_ARRAY_ITEM(netlists, i, nl) {
|
||||
if (top.empty() && nl->CellBaseName() != top)
|
||||
continue;
|
||||
nl->AddAtt(new Att(" \\top", NULL));
|
||||
nl_todo.insert(nl);
|
||||
}
|
||||
|
||||
delete netlists;
|
||||
|
||||
if (!verific_error_msg.empty())
|
||||
log_error("%s\n", verific_error_msg.c_str());
|
||||
|
||||
|
@ -1983,6 +2024,9 @@ struct VerificPass : public Pass {
|
|||
// WARNING: instantiating unknown module 'XYZ' (VERI-1063)
|
||||
Message::SetMessageType("VERI-1063", VERIFIC_ERROR);
|
||||
|
||||
// https://github.com/YosysHQ/yosys/issues/1055
|
||||
RuntimeFlags::SetVar("veri_elaborate_top_level_modules_having_interface_ports", 1) ;
|
||||
|
||||
#ifndef DB_PRESERVE_INITIAL_VALUE
|
||||
# warning Verific was built without DB_PRESERVE_INITIAL_VALUE.
|
||||
#endif
|
||||
|
@ -2212,8 +2256,8 @@ struct VerificPass : public Pass {
|
|||
continue;
|
||||
}
|
||||
if (args[argidx] == "-chparam" && argidx+2 < GetSize(args)) {
|
||||
const std::string &key = args[++argidx];
|
||||
const std::string &value = args[++argidx];
|
||||
const std::string &key = args[++argidx];
|
||||
const std::string &value = args[++argidx];
|
||||
unsigned new_insertion = parameters.Insert(key.c_str(), value.c_str(),
|
||||
1 /* force_overwrite */);
|
||||
if (!new_insertion)
|
||||
|
@ -2270,12 +2314,22 @@ struct VerificPass : public Pass {
|
|||
for (; argidx < GetSize(args); argidx++)
|
||||
{
|
||||
const char *name = args[argidx].c_str();
|
||||
VeriLibrary* veri_lib = veri_file::GetLibrary(work.c_str(), 1);
|
||||
|
||||
VeriModule *veri_module = veri_file::GetModule(name);
|
||||
if (veri_module) {
|
||||
log("Adding Verilog module '%s' to elaboration queue.\n", name);
|
||||
veri_modules.InsertLast(veri_module);
|
||||
continue;
|
||||
if (veri_lib) {
|
||||
VeriModule *veri_module = veri_lib->GetModule(name, 1);
|
||||
if (veri_module) {
|
||||
log("Adding Verilog module '%s' to elaboration queue.\n", name);
|
||||
veri_modules.InsertLast(veri_module);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Also elaborate all root modules since they may contain bind statements
|
||||
MapIter mi;
|
||||
FOREACH_VERILOG_MODULE_IN_LIBRARY(veri_lib, mi, veri_module) {
|
||||
if (!veri_module->IsRootModule()) continue;
|
||||
veri_modules.InsertLast(veri_module);
|
||||
}
|
||||
}
|
||||
|
||||
VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1);
|
||||
|
@ -2294,8 +2348,10 @@ struct VerificPass : public Pass {
|
|||
Netlist *nl;
|
||||
int i;
|
||||
|
||||
FOREACH_ARRAY_ITEM(netlists, i, nl)
|
||||
FOREACH_ARRAY_ITEM(netlists, i, nl) {
|
||||
nl->AddAtt(new Att(" \\top", NULL));
|
||||
nl_todo.insert(nl);
|
||||
}
|
||||
delete netlists;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ YOSYS_NAMESPACE_BEGIN
|
|||
extern int verific_verbose;
|
||||
|
||||
extern bool verific_import_pending;
|
||||
extern void verific_import(Design *design, std::string top = std::string());
|
||||
extern void verific_import(Design *design, const std::map<std::string,std::string> ¶meters, std::string top = std::string());
|
||||
|
||||
extern pool<int> verific_sva_prims;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l
|
|||
$(Q) mkdir -p $(dir $@)
|
||||
$(P) flex -o frontends/verilog/verilog_lexer.cc $<
|
||||
|
||||
frontends/verilog/verilog_parser.tab.o: CXXFLAGS += -DYYMAXDEPTH=100000
|
||||
frontends/verilog/verilog_parser.tab.o: CXXFLAGS += -DYYMAXDEPTH=10000000
|
||||
|
||||
OBJS += frontends/verilog/verilog_parser.tab.o
|
||||
OBJS += frontends/verilog/verilog_lexer.o
|
||||
|
|
|
@ -71,7 +71,7 @@ static int my_ilog2(int x)
|
|||
}
|
||||
|
||||
// parse a binary, decimal, hexadecimal or octal number with support for special bits ('x', 'z' and '?')
|
||||
static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type)
|
||||
static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type, bool is_unsized)
|
||||
{
|
||||
// all digits in string (MSB at index 0)
|
||||
std::vector<uint8_t> digits;
|
||||
|
@ -129,6 +129,9 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_unsized && (len > len_in_bits))
|
||||
log_file_error(current_filename, get_line_num(), "Unsized constant must have width of 1 bit, but have %d bits!\n", len);
|
||||
|
||||
for (len = len - 1; len >= 0; len--)
|
||||
if (data[len] == RTLIL::S1)
|
||||
break;
|
||||
|
@ -186,7 +189,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
|
|||
// Simple base-10 integer
|
||||
if (*endptr == 0) {
|
||||
std::vector<RTLIL::State> data;
|
||||
my_strtobin(data, str, -1, 10, case_type);
|
||||
my_strtobin(data, str, -1, 10, case_type, false);
|
||||
if (data.back() == RTLIL::S1)
|
||||
data.push_back(RTLIL::S0);
|
||||
return AstNode::mkconst_bits(data, true);
|
||||
|
@ -201,6 +204,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
|
|||
{
|
||||
std::vector<RTLIL::State> data;
|
||||
bool is_signed = false;
|
||||
bool is_unsized = false;
|
||||
if (*(endptr+1) == 's') {
|
||||
is_signed = true;
|
||||
endptr++;
|
||||
|
@ -209,28 +213,34 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
|
|||
{
|
||||
case 'b':
|
||||
case 'B':
|
||||
my_strtobin(data, endptr+2, len_in_bits, 2, case_type);
|
||||
my_strtobin(data, endptr+2, len_in_bits, 2, case_type, false);
|
||||
break;
|
||||
case 'o':
|
||||
case 'O':
|
||||
my_strtobin(data, endptr+2, len_in_bits, 8, case_type);
|
||||
my_strtobin(data, endptr+2, len_in_bits, 8, case_type, false);
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
my_strtobin(data, endptr+2, len_in_bits, 10, case_type);
|
||||
my_strtobin(data, endptr+2, len_in_bits, 10, case_type, false);
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
my_strtobin(data, endptr+2, len_in_bits, 16, case_type);
|
||||
my_strtobin(data, endptr+2, len_in_bits, 16, case_type, false);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
char next_char = char(tolower(*(endptr+1)));
|
||||
if (next_char == '0' || next_char == '1' || next_char == 'x' || next_char == 'z') {
|
||||
my_strtobin(data, endptr+1, 1, 2, case_type, true);
|
||||
is_unsized = true;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (len_in_bits < 0) {
|
||||
if (is_signed && data.back() == RTLIL::S1)
|
||||
data.push_back(RTLIL::S0);
|
||||
}
|
||||
return AstNode::mkconst_bits(data, is_signed);
|
||||
return AstNode::mkconst_bits(data, is_signed, is_unsized);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -158,6 +158,9 @@ struct VerilogFrontend : public Frontend {
|
|||
log(" delete (* whitebox *) and (* lib_whitebox *) attributes from\n");
|
||||
log(" all modules.\n");
|
||||
log("\n");
|
||||
log(" -specify\n");
|
||||
log(" parse and import specify blocks\n");
|
||||
log("\n");
|
||||
log(" -noopt\n");
|
||||
log(" don't perform basic optimizations (such as const folding) in the\n");
|
||||
log(" high-level front-end.\n");
|
||||
|
@ -228,6 +231,8 @@ struct VerilogFrontend : public Frontend {
|
|||
bool flag_nooverwrite = false;
|
||||
bool flag_overwrite = false;
|
||||
bool flag_defer = false;
|
||||
bool flag_noblackbox = false;
|
||||
bool flag_nowb = false;
|
||||
std::map<std::string, std::string> defines_map;
|
||||
std::list<std::string> include_dirs;
|
||||
std::list<std::string> attributes;
|
||||
|
@ -237,13 +242,10 @@ struct VerilogFrontend : public Frontend {
|
|||
formal_mode = false;
|
||||
norestrict_mode = false;
|
||||
assume_asserts_mode = false;
|
||||
noblackbox_mode = false;
|
||||
lib_mode = false;
|
||||
nowb_mode = false;
|
||||
specify_mode = false;
|
||||
default_nettype_wire = true;
|
||||
|
||||
log_header(design, "Executing Verilog-2005 frontend.\n");
|
||||
|
||||
args.insert(args.begin()+1, verilog_defaults.begin(), verilog_defaults.end());
|
||||
|
||||
size_t argidx;
|
||||
|
@ -342,7 +344,7 @@ struct VerilogFrontend : public Frontend {
|
|||
continue;
|
||||
}
|
||||
if (arg == "-noblackbox") {
|
||||
noblackbox_mode = true;
|
||||
flag_noblackbox = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-lib") {
|
||||
|
@ -351,7 +353,11 @@ struct VerilogFrontend : public Frontend {
|
|||
continue;
|
||||
}
|
||||
if (arg == "-nowb") {
|
||||
nowb_mode = true;
|
||||
flag_nowb = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-specify") {
|
||||
specify_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-noopt") {
|
||||
|
@ -415,6 +421,8 @@ struct VerilogFrontend : public Frontend {
|
|||
}
|
||||
extra_args(f, filename, args, argidx);
|
||||
|
||||
log_header(design, "Executing Verilog-2005 frontend: %s\n", filename.c_str());
|
||||
|
||||
log("Parsing %s%s input from `%s' to AST representation.\n",
|
||||
formal_mode ? "formal " : "", sv_mode ? "SystemVerilog" : "Verilog", filename.c_str());
|
||||
|
||||
|
@ -450,7 +458,7 @@ struct VerilogFrontend : public Frontend {
|
|||
error_on_dpi_function(current_ast);
|
||||
|
||||
AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches,
|
||||
flag_nomeminit, flag_nomem2reg, flag_mem2reg, noblackbox_mode, lib_mode, nowb_mode, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
|
||||
flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
|
||||
|
||||
if (!flag_nopp)
|
||||
delete lexin;
|
||||
|
|
|
@ -69,14 +69,11 @@ namespace VERILOG_FRONTEND
|
|||
// running in -assert-assumes mode
|
||||
extern bool assert_assumes_mode;
|
||||
|
||||
// running in -noblackbox mode
|
||||
extern bool noblackbox_mode;
|
||||
|
||||
// running in -lib mode
|
||||
extern bool lib_mode;
|
||||
|
||||
// running in -nowb mode
|
||||
extern bool nowb_mode;
|
||||
// running in -specify mode
|
||||
extern bool specify_mode;
|
||||
|
||||
// lexer input stream
|
||||
extern std::istream *lexin;
|
||||
|
|
|
@ -148,7 +148,7 @@ YOSYS_NAMESPACE_END
|
|||
"endfunction" { return TOK_ENDFUNCTION; }
|
||||
"task" { return TOK_TASK; }
|
||||
"endtask" { return TOK_ENDTASK; }
|
||||
"specify" { return TOK_SPECIFY; }
|
||||
"specify" { return specify_mode ? TOK_SPECIFY : TOK_IGNORED_SPECIFY; }
|
||||
"endspecify" { return TOK_ENDSPECIFY; }
|
||||
"specparam" { return TOK_SPECPARAM; }
|
||||
"package" { SV_KEYWORD(TOK_PACKAGE); }
|
||||
|
@ -206,7 +206,9 @@ YOSYS_NAMESPACE_END
|
|||
"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); }
|
||||
"checker" { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); }
|
||||
"endchecker" { if (formal_mode) return TOK_ENDCHECKER; SV_KEYWORD(TOK_ENDCHECKER); }
|
||||
"final" { SV_KEYWORD(TOK_FINAL); }
|
||||
"logic" { SV_KEYWORD(TOK_LOGIC); }
|
||||
"var" { SV_KEYWORD(TOK_VAR); }
|
||||
"bit" { SV_KEYWORD(TOK_REG); }
|
||||
|
||||
"eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
|
||||
|
@ -216,6 +218,8 @@ YOSYS_NAMESPACE_END
|
|||
"output" { return TOK_OUTPUT; }
|
||||
"inout" { return TOK_INOUT; }
|
||||
"wire" { return TOK_WIRE; }
|
||||
"wor" { return TOK_WOR; }
|
||||
"wand" { return TOK_WAND; }
|
||||
"reg" { return TOK_REG; }
|
||||
"integer" { return TOK_INTEGER; }
|
||||
"signed" { return TOK_SIGNED; }
|
||||
|
@ -230,7 +234,7 @@ YOSYS_NAMESPACE_END
|
|||
return TOK_CONSTVAL;
|
||||
}
|
||||
|
||||
[0-9]*[ \t]*\'s?[bodhBODH][ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
|
||||
[0-9]*[ \t]*\'s?[bodhBODH]*[ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
|
||||
frontend_verilog_yylval.string = new std::string(yytext);
|
||||
return TOK_CONSTVAL;
|
||||
}
|
||||
|
@ -301,6 +305,17 @@ supply1 { return TOK_SUPPLY1; }
|
|||
return TOK_ID;
|
||||
}
|
||||
|
||||
"$"(setup|hold|setuphold|removal|recovery|recrem|skew|timeskew|fullskew|nochange) {
|
||||
if (!specify_mode) REJECT;
|
||||
frontend_verilog_yylval.string = new std::string(yytext);
|
||||
return TOK_ID;
|
||||
}
|
||||
|
||||
"$"(info|warning|error|fatal) {
|
||||
frontend_verilog_yylval.string = new std::string(yytext);
|
||||
return TOK_ELAB_TASK;
|
||||
}
|
||||
|
||||
"$signed" { return TOK_TO_SIGNED; }
|
||||
"$unsigned" { return TOK_TO_UNSIGNED; }
|
||||
|
||||
|
@ -411,6 +426,17 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
|
|||
"+:" { return TOK_POS_INDEXED; }
|
||||
"-:" { return TOK_NEG_INDEXED; }
|
||||
|
||||
[-+]?[=*]> {
|
||||
if (!specify_mode) REJECT;
|
||||
frontend_verilog_yylval.string = new std::string(yytext);
|
||||
return TOK_SPECIFY_OPER;
|
||||
}
|
||||
|
||||
"&&&" {
|
||||
if (!specify_mode) REJECT;
|
||||
return TOK_SPECIFY_AND;
|
||||
}
|
||||
|
||||
"/*" { BEGIN(COMMENT); }
|
||||
<COMMENT>. /* ignore comment body */
|
||||
<COMMENT>\n /* ignore comment body */
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace VERILOG_FRONTEND {
|
|||
std::vector<char> case_type_stack;
|
||||
bool do_not_require_port_stubs;
|
||||
bool default_nettype_wire;
|
||||
bool sv_mode, formal_mode, noblackbox_mode, lib_mode, nowb_mode;
|
||||
bool sv_mode, formal_mode, lib_mode, specify_mode;
|
||||
bool noassert_mode, noassume_mode, norestrict_mode;
|
||||
bool assume_asserts_mode, assert_assumes_mode;
|
||||
bool current_wire_rand, current_wire_const;
|
||||
|
@ -94,29 +94,58 @@ static void free_attr(std::map<std::string, AstNode*> *al)
|
|||
delete al;
|
||||
}
|
||||
|
||||
struct specify_target {
|
||||
char polarity_op;
|
||||
AstNode *dst, *dat;
|
||||
};
|
||||
|
||||
struct specify_triple {
|
||||
AstNode *t_min, *t_avg, *t_max;
|
||||
};
|
||||
|
||||
struct specify_rise_fall {
|
||||
specify_triple rise;
|
||||
specify_triple fall;
|
||||
};
|
||||
|
||||
%}
|
||||
|
||||
%name-prefix "frontend_verilog_yy"
|
||||
%define api.prefix {frontend_verilog_yy}
|
||||
|
||||
/* The union is defined in the header, so we need to provide all the
|
||||
* includes it requires
|
||||
*/
|
||||
%code requires {
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "frontends/verilog/verilog_frontend.h"
|
||||
}
|
||||
|
||||
%union {
|
||||
std::string *string;
|
||||
struct YOSYS_NAMESPACE_PREFIX AST::AstNode *ast;
|
||||
std::map<std::string, YOSYS_NAMESPACE_PREFIX AST::AstNode*> *al;
|
||||
struct specify_target *specify_target_ptr;
|
||||
struct specify_triple *specify_triple_ptr;
|
||||
struct specify_rise_fall *specify_rise_fall_ptr;
|
||||
bool boolean;
|
||||
char ch;
|
||||
}
|
||||
|
||||
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE TOK_SVA_LABEL
|
||||
%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER
|
||||
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
|
||||
%token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_ELAB_TASK
|
||||
%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL
|
||||
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
|
||||
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
|
||||
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
|
||||
%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT
|
||||
%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC
|
||||
%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT TOK_VAR
|
||||
%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_WAND TOK_WOR TOK_REG TOK_LOGIC
|
||||
%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL
|
||||
%token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT
|
||||
%token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC
|
||||
%token TOK_CASE TOK_CASEX TOK_CASEZ TOK_ENDCASE TOK_DEFAULT
|
||||
%token TOK_FUNCTION TOK_ENDFUNCTION TOK_TASK TOK_ENDTASK TOK_SPECIFY TOK_ENDSPECIFY TOK_SPECPARAM
|
||||
%token TOK_FUNCTION TOK_ENDFUNCTION TOK_TASK TOK_ENDTASK TOK_SPECIFY
|
||||
%token TOK_IGNORED_SPECIFY TOK_ENDSPECIFY TOK_SPECPARAM TOK_SPECIFY_AND
|
||||
%token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL
|
||||
%token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE
|
||||
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
|
||||
|
@ -130,6 +159,12 @@ static void free_attr(std::map<std::string, AstNode*> *al)
|
|||
%type <boolean> opt_signed opt_property unique_case_attr
|
||||
%type <al> attr case_attr
|
||||
|
||||
%type <specify_target_ptr> specify_target
|
||||
%type <specify_triple_ptr> specify_triple
|
||||
%type <specify_rise_fall_ptr> specify_rise_fall
|
||||
%type <ast> specify_if specify_condition specify_opt_arg
|
||||
%type <ch> specify_edge
|
||||
|
||||
// operator precedence from low to high
|
||||
%left OP_LOR
|
||||
%left OP_LAND
|
||||
|
@ -450,12 +485,21 @@ wire_type_token_io:
|
|||
wire_type_token:
|
||||
TOK_WIRE {
|
||||
} |
|
||||
TOK_WOR {
|
||||
astbuf3->is_wor = true;
|
||||
} |
|
||||
TOK_WAND {
|
||||
astbuf3->is_wand = true;
|
||||
} |
|
||||
TOK_REG {
|
||||
astbuf3->is_reg = true;
|
||||
} |
|
||||
TOK_LOGIC {
|
||||
astbuf3->is_logic = true;
|
||||
} |
|
||||
TOK_VAR {
|
||||
astbuf3->is_logic = true;
|
||||
} |
|
||||
TOK_INTEGER {
|
||||
astbuf3->is_reg = true;
|
||||
astbuf3->range_left = 31;
|
||||
|
@ -539,7 +583,7 @@ module_body:
|
|||
|
||||
module_body_stmt:
|
||||
task_func_decl | specify_block |param_decl | localparam_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |
|
||||
always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl;
|
||||
always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block;
|
||||
|
||||
checker_decl:
|
||||
TOK_CHECKER TOK_ID ';' {
|
||||
|
@ -697,15 +741,254 @@ task_func_body:
|
|||
task_func_body behavioral_stmt |
|
||||
/* empty */;
|
||||
|
||||
specify_block:
|
||||
TOK_SPECIFY specify_item_opt TOK_ENDSPECIFY |
|
||||
TOK_SPECIFY TOK_ENDSPECIFY ;
|
||||
/*************************** specify parser ***************************/
|
||||
|
||||
specify_item_opt:
|
||||
specify_item_opt specify_item |
|
||||
specify_item ;
|
||||
specify_block:
|
||||
TOK_SPECIFY specify_item_list TOK_ENDSPECIFY;
|
||||
|
||||
specify_item_list:
|
||||
specify_item specify_item_list |
|
||||
/* empty */;
|
||||
|
||||
specify_item:
|
||||
specify_if '(' specify_edge expr TOK_SPECIFY_OPER specify_target ')' '=' specify_rise_fall ';' {
|
||||
AstNode *en_expr = $1;
|
||||
char specify_edge = $3;
|
||||
AstNode *src_expr = $4;
|
||||
string *oper = $5;
|
||||
specify_target *target = $6;
|
||||
specify_rise_fall *timing = $9;
|
||||
|
||||
if (specify_edge != 0 && target->dat == nullptr)
|
||||
frontend_verilog_yyerror("Found specify edge but no data spec.\n");
|
||||
|
||||
AstNode *cell = new AstNode(AST_CELL);
|
||||
ast_stack.back()->children.push_back(cell);
|
||||
cell->str = stringf("$specify$%d", autoidx++);
|
||||
cell->children.push_back(new AstNode(AST_CELLTYPE));
|
||||
cell->children.back()->str = target->dat ? "$specify3" : "$specify2";
|
||||
|
||||
char oper_polarity = 0;
|
||||
char oper_type = oper->at(0);
|
||||
|
||||
if (oper->size() == 3) {
|
||||
oper_polarity = oper->at(0);
|
||||
oper_type = oper->at(1);
|
||||
}
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(oper_type == '*', false, 1)));
|
||||
cell->children.back()->str = "\\FULL";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(oper_polarity != 0, false, 1)));
|
||||
cell->children.back()->str = "\\SRC_DST_PEN";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(oper_polarity == '+', false, 1)));
|
||||
cell->children.back()->str = "\\SRC_DST_POL";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, timing->rise.t_min));
|
||||
cell->children.back()->str = "\\T_RISE_MIN";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, timing->rise.t_avg));
|
||||
cell->children.back()->str = "\\T_RISE_TYP";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, timing->rise.t_max));
|
||||
cell->children.back()->str = "\\T_RISE_MAX";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, timing->fall.t_min));
|
||||
cell->children.back()->str = "\\T_FALL_MIN";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, timing->fall.t_avg));
|
||||
cell->children.back()->str = "\\T_FALL_TYP";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, timing->fall.t_max));
|
||||
cell->children.back()->str = "\\T_FALL_MAX";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_ARGUMENT, en_expr ? en_expr : AstNode::mkconst_int(1, false, 1)));
|
||||
cell->children.back()->str = "\\EN";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_ARGUMENT, src_expr));
|
||||
cell->children.back()->str = "\\SRC";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_ARGUMENT, target->dst));
|
||||
cell->children.back()->str = "\\DST";
|
||||
|
||||
if (target->dat)
|
||||
{
|
||||
cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(specify_edge != 0, false, 1)));
|
||||
cell->children.back()->str = "\\EDGE_EN";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(specify_edge == 'p', false, 1)));
|
||||
cell->children.back()->str = "\\EDGE_POL";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(target->polarity_op != 0, false, 1)));
|
||||
cell->children.back()->str = "\\DAT_DST_PEN";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(target->polarity_op == '+', false, 1)));
|
||||
cell->children.back()->str = "\\DAT_DST_POL";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_ARGUMENT, target->dat));
|
||||
cell->children.back()->str = "\\DAT";
|
||||
}
|
||||
|
||||
delete oper;
|
||||
delete target;
|
||||
delete timing;
|
||||
} |
|
||||
TOK_ID '(' specify_edge expr specify_condition ',' specify_edge expr specify_condition ',' expr specify_opt_arg ')' ';' {
|
||||
if (*$1 != "$setup" && *$1 != "$hold" && *$1 != "$setuphold" && *$1 != "$removal" && *$1 != "$recovery" &&
|
||||
*$1 != "$recrem" && *$1 != "$skew" && *$1 != "$timeskew" && *$1 != "$fullskew" && *$1 != "$nochange")
|
||||
frontend_verilog_yyerror("Unsupported specify rule type: %s\n", $1->c_str());
|
||||
|
||||
AstNode *src_pen = AstNode::mkconst_int($3 != 0, false, 1);
|
||||
AstNode *src_pol = AstNode::mkconst_int($3 == 'p', false, 1);
|
||||
AstNode *src_expr = $4, *src_en = $5 ? $5 : AstNode::mkconst_int(1, false, 1);
|
||||
|
||||
AstNode *dst_pen = AstNode::mkconst_int($7 != 0, false, 1);
|
||||
AstNode *dst_pol = AstNode::mkconst_int($7 == 'p', false, 1);
|
||||
AstNode *dst_expr = $8, *dst_en = $9 ? $9 : AstNode::mkconst_int(1, false, 1);
|
||||
|
||||
AstNode *limit = $11;
|
||||
AstNode *limit2 = $12;
|
||||
|
||||
AstNode *cell = new AstNode(AST_CELL);
|
||||
ast_stack.back()->children.push_back(cell);
|
||||
cell->str = stringf("$specify$%d", autoidx++);
|
||||
cell->children.push_back(new AstNode(AST_CELLTYPE));
|
||||
cell->children.back()->str = "$specrule";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_str(*$1)));
|
||||
cell->children.back()->str = "\\TYPE";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, limit));
|
||||
cell->children.back()->str = "\\T_LIMIT";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2 : AstNode::mkconst_int(0, true)));
|
||||
cell->children.back()->str = "\\T_LIMIT2";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, src_pen));
|
||||
cell->children.back()->str = "\\SRC_PEN";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, src_pol));
|
||||
cell->children.back()->str = "\\SRC_POL";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, dst_pen));
|
||||
cell->children.back()->str = "\\DST_PEN";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_PARASET, dst_pol));
|
||||
cell->children.back()->str = "\\DST_POL";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_ARGUMENT, src_en));
|
||||
cell->children.back()->str = "\\SRC_EN";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_ARGUMENT, src_expr));
|
||||
cell->children.back()->str = "\\SRC";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_ARGUMENT, dst_en));
|
||||
cell->children.back()->str = "\\DST_EN";
|
||||
|
||||
cell->children.push_back(new AstNode(AST_ARGUMENT, dst_expr));
|
||||
cell->children.back()->str = "\\DST";
|
||||
|
||||
delete $1;
|
||||
};
|
||||
|
||||
specify_opt_arg:
|
||||
',' expr {
|
||||
$$ = $2;
|
||||
} |
|
||||
/* empty */ {
|
||||
$$ = nullptr;
|
||||
};
|
||||
|
||||
specify_if:
|
||||
TOK_IF '(' expr ')' {
|
||||
$$ = $3;
|
||||
} |
|
||||
/* empty */ {
|
||||
$$ = nullptr;
|
||||
};
|
||||
|
||||
specify_condition:
|
||||
TOK_SPECIFY_AND expr {
|
||||
$$ = $2;
|
||||
} |
|
||||
/* empty */ {
|
||||
$$ = nullptr;
|
||||
};
|
||||
|
||||
specify_target:
|
||||
expr {
|
||||
$$ = new specify_target;
|
||||
$$->polarity_op = 0;
|
||||
$$->dst = $1;
|
||||
$$->dat = nullptr;
|
||||
} |
|
||||
'(' expr ':' expr ')'{
|
||||
$$ = new specify_target;
|
||||
$$->polarity_op = 0;
|
||||
$$->dst = $2;
|
||||
$$->dat = $4;
|
||||
} |
|
||||
'(' expr TOK_NEG_INDEXED expr ')'{
|
||||
$$ = new specify_target;
|
||||
$$->polarity_op = '-';
|
||||
$$->dst = $2;
|
||||
$$->dat = $4;
|
||||
} |
|
||||
'(' expr TOK_POS_INDEXED expr ')'{
|
||||
$$ = new specify_target;
|
||||
$$->polarity_op = '+';
|
||||
$$->dst = $2;
|
||||
$$->dat = $4;
|
||||
};
|
||||
|
||||
specify_edge:
|
||||
TOK_POSEDGE { $$ = 'p'; } |
|
||||
TOK_NEGEDGE { $$ = 'n'; } |
|
||||
{ $$ = 0; };
|
||||
|
||||
specify_rise_fall:
|
||||
specify_triple {
|
||||
$$ = new specify_rise_fall;
|
||||
$$->rise = *$1;
|
||||
$$->fall.t_min = $1->t_min->clone();
|
||||
$$->fall.t_avg = $1->t_avg->clone();
|
||||
$$->fall.t_max = $1->t_max->clone();
|
||||
delete $1;
|
||||
} |
|
||||
'(' specify_triple ',' specify_triple ')' {
|
||||
$$ = new specify_rise_fall;
|
||||
$$->rise = *$2;
|
||||
$$->fall = *$4;
|
||||
delete $2;
|
||||
delete $4;
|
||||
};
|
||||
|
||||
specify_triple:
|
||||
expr {
|
||||
$$ = new specify_triple;
|
||||
$$->t_min = $1;
|
||||
$$->t_avg = $1->clone();
|
||||
$$->t_max = $1->clone();
|
||||
} |
|
||||
expr ':' expr ':' expr {
|
||||
$$ = new specify_triple;
|
||||
$$->t_min = $1;
|
||||
$$->t_avg = $3;
|
||||
$$->t_max = $5;
|
||||
};
|
||||
|
||||
/******************** ignored specify parser **************************/
|
||||
|
||||
ignored_specify_block:
|
||||
TOK_IGNORED_SPECIFY ignored_specify_item_opt TOK_ENDSPECIFY |
|
||||
TOK_IGNORED_SPECIFY TOK_ENDSPECIFY ;
|
||||
|
||||
ignored_specify_item_opt:
|
||||
ignored_specify_item_opt ignored_specify_item |
|
||||
ignored_specify_item ;
|
||||
|
||||
ignored_specify_item:
|
||||
specparam_declaration
|
||||
// | pulsestyle_declaration
|
||||
// | showcancelled_declaration
|
||||
|
@ -721,13 +1004,13 @@ specparam_declaration:
|
|||
// and the 'non_opt_range' rule allows index ranges not allowed by 1364-2005
|
||||
// exxxxtending this for SV specparam would change this anyhow
|
||||
specparam_range:
|
||||
'[' constant_expression ':' constant_expression ']' ;
|
||||
'[' ignspec_constant_expression ':' ignspec_constant_expression ']' ;
|
||||
|
||||
list_of_specparam_assignments:
|
||||
specparam_assignment | list_of_specparam_assignments ',' specparam_assignment;
|
||||
|
||||
specparam_assignment:
|
||||
TOK_ID '=' constant_mintypmax_expression ;
|
||||
ignspec_id '=' constant_mintypmax_expression ;
|
||||
|
||||
/*
|
||||
pulsestyle_declaration :
|
||||
|
@ -802,19 +1085,19 @@ opt_polarity_operator :
|
|||
|
||||
// Good enough for the time being
|
||||
specify_input_terminal_descriptor :
|
||||
TOK_ID ;
|
||||
ignspec_id ;
|
||||
|
||||
// Good enough for the time being
|
||||
specify_output_terminal_descriptor :
|
||||
TOK_ID ;
|
||||
ignspec_id ;
|
||||
|
||||
system_timing_declaration :
|
||||
TOK_ID '(' system_timing_args ')' ';' ;
|
||||
ignspec_id '(' system_timing_args ')' ';' ;
|
||||
|
||||
system_timing_arg :
|
||||
TOK_POSEDGE TOK_ID |
|
||||
TOK_NEGEDGE TOK_ID |
|
||||
expr ;
|
||||
TOK_POSEDGE ignspec_id |
|
||||
TOK_NEGEDGE ignspec_id |
|
||||
ignspec_expr ;
|
||||
|
||||
system_timing_args :
|
||||
system_timing_arg |
|
||||
|
@ -871,19 +1154,27 @@ tzx_path_delay_expression :
|
|||
*/
|
||||
|
||||
path_delay_expression :
|
||||
constant_expression;
|
||||
ignspec_constant_expression;
|
||||
|
||||
constant_mintypmax_expression :
|
||||
constant_expression
|
||||
| constant_expression ':' constant_expression ':' constant_expression
|
||||
ignspec_constant_expression
|
||||
| ignspec_constant_expression ':' ignspec_constant_expression ':' ignspec_constant_expression
|
||||
;
|
||||
|
||||
// for the time being this is OK, but we may write our own expr here.
|
||||
// as I'm not sure it is legal to use a full expr here (probably not)
|
||||
// On the other hand, other rules requiring constant expressions also use 'expr'
|
||||
// (such as param assignment), so we may leave this as-is, perhaps adding runtime checks for constant-ness
|
||||
constant_expression:
|
||||
expr ;
|
||||
ignspec_constant_expression:
|
||||
expr { delete $1; };
|
||||
|
||||
ignspec_expr:
|
||||
expr { delete $1; };
|
||||
|
||||
ignspec_id:
|
||||
TOK_ID { delete $1; };
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
param_signed:
|
||||
TOK_SIGNED {
|
||||
|
@ -917,7 +1208,7 @@ param_range:
|
|||
};
|
||||
|
||||
param_decl:
|
||||
TOK_PARAMETER {
|
||||
attr TOK_PARAMETER {
|
||||
astbuf1 = new AstNode(AST_PARAMETER);
|
||||
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
|
||||
} param_signed param_integer param_real param_range param_decl_list ';' {
|
||||
|
@ -925,7 +1216,7 @@ param_decl:
|
|||
};
|
||||
|
||||
localparam_decl:
|
||||
TOK_LOCALPARAM {
|
||||
attr TOK_LOCALPARAM {
|
||||
astbuf1 = new AstNode(AST_LOCALPARAM);
|
||||
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
|
||||
} param_signed param_integer param_real param_range param_decl_list ';' {
|
||||
|
@ -1241,27 +1532,40 @@ cell_port_list_rules:
|
|||
cell_port | cell_port_list_rules ',' cell_port;
|
||||
|
||||
cell_port:
|
||||
/* empty */ {
|
||||
attr {
|
||||
AstNode *node = new AstNode(AST_ARGUMENT);
|
||||
astbuf2->children.push_back(node);
|
||||
free_attr($1);
|
||||
} |
|
||||
expr {
|
||||
attr expr {
|
||||
AstNode *node = new AstNode(AST_ARGUMENT);
|
||||
astbuf2->children.push_back(node);
|
||||
node->children.push_back($1);
|
||||
node->children.push_back($2);
|
||||
free_attr($1);
|
||||
} |
|
||||
'.' TOK_ID '(' expr ')' {
|
||||
attr '.' TOK_ID '(' expr ')' {
|
||||
AstNode *node = new AstNode(AST_ARGUMENT);
|
||||
node->str = *$2;
|
||||
node->str = *$3;
|
||||
astbuf2->children.push_back(node);
|
||||
node->children.push_back($4);
|
||||
delete $2;
|
||||
node->children.push_back($5);
|
||||
delete $3;
|
||||
free_attr($1);
|
||||
} |
|
||||
'.' TOK_ID '(' ')' {
|
||||
attr '.' TOK_ID '(' ')' {
|
||||
AstNode *node = new AstNode(AST_ARGUMENT);
|
||||
node->str = *$2;
|
||||
node->str = *$3;
|
||||
astbuf2->children.push_back(node);
|
||||
delete $2;
|
||||
delete $3;
|
||||
free_attr($1);
|
||||
} |
|
||||
attr '.' TOK_ID {
|
||||
AstNode *node = new AstNode(AST_ARGUMENT);
|
||||
node->str = *$3;
|
||||
astbuf2->children.push_back(node);
|
||||
node->children.push_back(new AstNode(AST_IDENTIFIER));
|
||||
node->children.back()->str = *$3;
|
||||
delete $3;
|
||||
free_attr($1);
|
||||
};
|
||||
|
||||
always_stmt:
|
||||
|
@ -1341,6 +1645,9 @@ opt_property:
|
|||
TOK_PROPERTY {
|
||||
$$ = true;
|
||||
} |
|
||||
TOK_FINAL {
|
||||
$$ = false;
|
||||
} |
|
||||
/* empty */ {
|
||||
$$ = false;
|
||||
};
|
||||
|
@ -1869,6 +2176,15 @@ gen_stmt:
|
|||
if ($6 != NULL)
|
||||
delete $6;
|
||||
ast_stack.pop_back();
|
||||
} |
|
||||
TOK_ELAB_TASK {
|
||||
AstNode *node = new AstNode(AST_TECALL);
|
||||
node->str = *$1;
|
||||
delete $1;
|
||||
ast_stack.back()->children.push_back(node);
|
||||
ast_stack.push_back(node);
|
||||
} opt_arg_list ';'{
|
||||
ast_stack.pop_back();
|
||||
};
|
||||
|
||||
gen_stmt_block:
|
||||
|
@ -2139,4 +2455,3 @@ concat_list:
|
|||
$$ = $3;
|
||||
$$->children.push_back($1);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue