mirror of https://github.com/YosysHQ/yosys.git
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
6d2ea6fe55
10
.travis.yml
10
.travis.yml
|
@ -132,11 +132,11 @@ matrix:
|
|||
env:
|
||||
- MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0"
|
||||
|
||||
# Latest clang on Mac OS X
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
env:
|
||||
- MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++"
|
||||
# # Latest clang on Mac OS X
|
||||
# - os: osx
|
||||
# osx_image: xcode9.4
|
||||
# env:
|
||||
# - MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++"
|
||||
|
||||
before_install:
|
||||
- ./.travis/setup.sh
|
||||
|
|
22
README.md
22
README.md
|
@ -34,11 +34,24 @@ compatible license that is similar in terms to the MIT license
|
|||
or the 2-clause BSD license).
|
||||
|
||||
|
||||
Web Site
|
||||
========
|
||||
Web Site and Other Resources
|
||||
============================
|
||||
|
||||
More information and documentation can be found on the Yosys web site:
|
||||
http://www.clifford.at/yosys/
|
||||
- http://www.clifford.at/yosys/
|
||||
|
||||
The "Documentation" page on the web site contains links to more resources,
|
||||
including a manual that even describes some of the Yosys internals:
|
||||
- http://www.clifford.at/yosys/documentation.html
|
||||
|
||||
The file `CodingReadme` in this directory contains additional information
|
||||
for people interested in using the Yosys C++ APIs.
|
||||
|
||||
Users interested in formal verification might want to use the formal verification
|
||||
front-end for Yosys, SymbiYosys:
|
||||
- https://symbiyosys.readthedocs.io/en/latest/
|
||||
- https://github.com/YosysHQ/SymbiYosys
|
||||
|
||||
|
||||
Setup
|
||||
======
|
||||
|
@ -296,6 +309,9 @@ Verilog Attributes and non-standard features
|
|||
passes to identify input and output ports of cells. The Verilog backend
|
||||
also does not output blackbox modules on default.
|
||||
|
||||
- The ``dynports'' attribute is used by the Verilog front-end to mark modules
|
||||
that have ports with a width that depends on a parameter.
|
||||
|
||||
- The ``keep`` attribute on cells and wires is used to mark objects that should
|
||||
never be removed by the optimizer. This is used for example for cells that
|
||||
have hidden connections that are not part of the netlist, such as IO pads.
|
||||
|
|
|
@ -130,7 +130,7 @@ struct EdifBackend : public Backend {
|
|||
bool port_rename = false;
|
||||
bool attr_properties = false;
|
||||
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
|
||||
bool nogndvcc = false, gndvccy = true;
|
||||
bool nogndvcc = false, gndvccy = false;
|
||||
CellTypes ct(design);
|
||||
EdifNames edif_names;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ new_project \
|
|||
import_files -hdl_source {netlist.vm}
|
||||
import_files -sdc {example.sdc}
|
||||
import_files -io_pdc {example.pdc}
|
||||
build_design_hierarchy
|
||||
set_option -synth 0
|
||||
|
||||
organize_tool_files -tool PLACEROUTE \
|
||||
|
@ -32,22 +33,25 @@ configure_tool -name PLACEROUTE \
|
|||
-params EFFORT_LEVEL:false \
|
||||
-params REPAIR_MIN_DELAY:false
|
||||
|
||||
puts ""
|
||||
puts "**> COMPILE"
|
||||
run_tool -name {COMPILE}
|
||||
puts "<** COMPILE"
|
||||
|
||||
puts ""
|
||||
puts "**> PLACEROUTE"
|
||||
run_tool -name {PLACEROUTE}
|
||||
puts "<** PLACEROUTE"
|
||||
|
||||
puts ""
|
||||
puts "**> VERIFYTIMING"
|
||||
run_tool -name {VERIFYTIMING}
|
||||
puts "<** VERIFYTIMING"
|
||||
|
||||
save_project
|
||||
|
||||
# puts "**> export_bitstream"
|
||||
# export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC}
|
||||
# puts "<** export_bitstream"
|
||||
puts ""
|
||||
puts "**> BITSTREAM"
|
||||
export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC}
|
||||
puts "<** BITSTREAM"
|
||||
|
||||
puts ""
|
||||
exit 0
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v
|
||||
LM_LICENSE_FILE=1702@`hostname` /opt/microsemi/Libero_SoC_v11.9/Libero/bin/libero SCRIPT:libero.tcl
|
||||
export LM_LICENSE_FILE=${LM_LICENSE_FILE:-1702@localhost}
|
||||
/opt/microsemi/Libero_SoC_v12.0/Libero/bin/libero SCRIPT:libero.tcl
|
||||
cp proj/designer/example/export/example.stp .
|
||||
|
|
|
@ -214,6 +214,8 @@ namespace AST
|
|||
MEM2REG_FL_SET_ASYNC = 0x00000800,
|
||||
MEM2REG_FL_EQ2 = 0x00001000,
|
||||
MEM2REG_FL_CMPLX_LHS = 0x00002000,
|
||||
MEM2REG_FL_CONST_LHS = 0x00004000,
|
||||
MEM2REG_FL_VAR_LHS = 0x00008000,
|
||||
|
||||
/* proc flags */
|
||||
MEM2REG_FL_EQ1 = 0x01000000,
|
||||
|
@ -237,6 +239,7 @@ namespace AST
|
|||
bool has_const_only_constructs(bool &recommend_const_eval);
|
||||
void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);
|
||||
AstNode *eval_const_function(AstNode *fcall);
|
||||
bool is_simple_const_expr();
|
||||
|
||||
// create a human-readable text representation of the AST (for debugging)
|
||||
void dumpAst(FILE *f, std::string indent) const;
|
||||
|
|
|
@ -544,7 +544,11 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
break;
|
||||
|
||||
case AST_WIRE:
|
||||
log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n");
|
||||
log_file_error(ast->filename, ast->linenum, "Found reg declaration in block without label!\n");
|
||||
break;
|
||||
|
||||
case AST_ASSIGN:
|
||||
log_file_error(ast->filename, ast->linenum, "Found continous assignment in always/initial block!\n");
|
||||
break;
|
||||
|
||||
case AST_PARAMETER:
|
||||
|
|
|
@ -113,6 +113,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS)
|
||||
goto verbose_activate;
|
||||
|
||||
if ((memflags & AstNode::MEM2REG_FL_CONST_LHS) && !(memflags & AstNode::MEM2REG_FL_VAR_LHS))
|
||||
goto verbose_activate;
|
||||
|
||||
// log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
|
||||
continue;
|
||||
|
||||
|
@ -325,6 +328,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
for (size_t i = 0; i < children.size(); i++) {
|
||||
AstNode *node = children[i];
|
||||
if (node->type == AST_WIRE) {
|
||||
if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
|
||||
for (auto c : node->children[0]->children) {
|
||||
if (!c->is_simple_const_expr()) {
|
||||
if (attributes.count("\\dynports"))
|
||||
delete attributes.at("\\dynports");
|
||||
attributes["\\dynports"] = AstNode::mkconst_int(1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this_wire_scope.count(node->str) > 0) {
|
||||
AstNode *first_node = this_wire_scope[node->str];
|
||||
if (first_node->is_input && node->is_reg)
|
||||
|
@ -938,7 +950,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
}
|
||||
}
|
||||
if (current_scope.count(str) == 0) {
|
||||
if (flag_autowire) {
|
||||
if (flag_autowire || str == "\\$global_clock") {
|
||||
AstNode *auto_wire = new AstNode(AST_AUTOWIRE);
|
||||
auto_wire->str = str;
|
||||
current_ast_mod->children.push_back(auto_wire);
|
||||
|
@ -2169,6 +2181,8 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
}
|
||||
|
||||
newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init);
|
||||
delete node_filename;
|
||||
delete node_memory;
|
||||
goto apply_newNode;
|
||||
}
|
||||
|
||||
|
@ -2936,6 +2950,14 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
|
|||
proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
|
||||
}
|
||||
|
||||
// remember if this is a constant index or not
|
||||
if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) {
|
||||
if (children[0]->children[0]->children[0]->type == AST_CONSTANT)
|
||||
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS;
|
||||
else
|
||||
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS;
|
||||
}
|
||||
|
||||
// remember where this is
|
||||
if (flags & MEM2REG_FL_INIT) {
|
||||
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
|
||||
|
@ -3048,6 +3070,39 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
|
|||
if (type == AST_FUNCTION || type == AST_TASK)
|
||||
return false;
|
||||
|
||||
if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast))
|
||||
{
|
||||
log_assert(children[0]->type == AST_CONSTANT);
|
||||
log_assert(children[1]->type == AST_CONSTANT);
|
||||
log_assert(children[2]->type == AST_CONSTANT);
|
||||
|
||||
int cursor = children[0]->asInt(false);
|
||||
Const data = children[1]->bitsAsConst();
|
||||
int length = children[2]->asInt(false);
|
||||
|
||||
if (length != 0)
|
||||
{
|
||||
AstNode *block = new AstNode(AST_INITIAL, new AstNode(AST_BLOCK));
|
||||
mod->children.push_back(block);
|
||||
block = block->children[0];
|
||||
|
||||
int wordsz = GetSize(data) / length;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false))), mkconst_bits(data.extract(i*wordsz, wordsz).bits, false)));
|
||||
block->children.back()->children[0]->str = str;
|
||||
block->children.back()->children[0]->id2ast = id2ast;
|
||||
block->children.back()->children[0]->was_checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
AstNode *newNode = new AstNode(AST_NONE);
|
||||
newNode->cloneInto(this);
|
||||
delete newNode;
|
||||
|
||||
did_something = true;
|
||||
}
|
||||
|
||||
if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set))
|
||||
{
|
||||
if (async_block == NULL) {
|
||||
|
@ -3277,6 +3332,16 @@ bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool AstNode::is_simple_const_expr()
|
||||
{
|
||||
if (type == AST_IDENTIFIER)
|
||||
return false;
|
||||
for (auto child : children)
|
||||
if (!child->is_simple_const_expr())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// helper function for AstNode::eval_const_function()
|
||||
void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall)
|
||||
{
|
||||
|
|
|
@ -910,7 +910,7 @@ struct HierarchyPass : public Pass {
|
|||
if (m == nullptr)
|
||||
continue;
|
||||
|
||||
if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty()) {
|
||||
if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
|
||||
IdString new_m_name = m->derive(design, cell->parameters, true);
|
||||
if (new_m_name.empty())
|
||||
continue;
|
||||
|
|
|
@ -5,4 +5,4 @@ EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h
|
|||
.SECONDARY: passes/pmgen/ice40_dsp_pm.h
|
||||
|
||||
passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg
|
||||
$(P) mkdir -p passes/pmgen && python3 $^
|
||||
$(P) mkdir -p passes/pmgen && python3 $^ $@
|
||||
|
|
|
@ -9,7 +9,8 @@ pp = pprint.PrettyPrinter(indent=4)
|
|||
pmgfile = sys.argv[1]
|
||||
assert pmgfile.endswith(".pmg")
|
||||
prefix = pmgfile[0:-4]
|
||||
pmname = prefix.split('/')[-1]
|
||||
prefix = prefix.split('/')[-1]
|
||||
outfile = sys.argv[2]
|
||||
|
||||
state_types = dict()
|
||||
udata_types = dict()
|
||||
|
@ -179,7 +180,7 @@ with open(pmgfile, "r") as f:
|
|||
|
||||
blocks.append(block)
|
||||
|
||||
with open("%s_pm.h" % prefix, "w") as f:
|
||||
with open(outfile, "w") as f:
|
||||
print("// Generated by pmgen.py from {}.pgm".format(prefix), file=f)
|
||||
print("", file=f)
|
||||
|
||||
|
@ -190,10 +191,10 @@ with open("%s_pm.h" % prefix, "w") as f:
|
|||
print("YOSYS_NAMESPACE_BEGIN", file=f)
|
||||
print("", file=f)
|
||||
|
||||
print("struct {}_pm {{".format(pmname), file=f)
|
||||
print("struct {}_pm {{".format(prefix), file=f)
|
||||
print(" Module *module;", file=f)
|
||||
print(" SigMap sigmap;", file=f)
|
||||
print(" std::function<void()> on_accept;".format(pmname), file=f)
|
||||
print(" std::function<void()> on_accept;".format(prefix), file=f)
|
||||
print("", file=f)
|
||||
|
||||
for index in range(len(blocks)):
|
||||
|
@ -291,7 +292,7 @@ with open("%s_pm.h" % prefix, "w") as f:
|
|||
print(" }", file=f)
|
||||
print("", file=f)
|
||||
|
||||
print(" {}_pm(Module *module, const vector<Cell*> &cells) :".format(pmname), file=f)
|
||||
print(" {}_pm(Module *module, const vector<Cell*> &cells) :".format(prefix), file=f)
|
||||
print(" module(module), sigmap(module) {", file=f)
|
||||
for s, t in sorted(udata_types.items()):
|
||||
if t.endswith("*"):
|
||||
|
@ -321,7 +322,7 @@ with open("%s_pm.h" % prefix, "w") as f:
|
|||
print(" }", file=f)
|
||||
print("", file=f)
|
||||
|
||||
print(" ~{}_pm() {{".format(pmname), file=f)
|
||||
print(" ~{}_pm() {{".format(prefix), file=f)
|
||||
print(" for (auto cell : autoremove_cells)", file=f)
|
||||
print(" module->remove(cell);", file=f)
|
||||
print(" }", file=f)
|
||||
|
@ -340,7 +341,7 @@ with open("%s_pm.h" % prefix, "w") as f:
|
|||
print(" }", file=f)
|
||||
print("", file=f)
|
||||
|
||||
print(" void run(std::function<void({}_pm&)> on_accept_f) {{".format(pmname), file=f)
|
||||
print(" void run(std::function<void({}_pm&)> on_accept_f) {{".format(prefix), file=f)
|
||||
print(" run([&](){on_accept_f(*this);});", file=f)
|
||||
print(" }", file=f)
|
||||
print("", file=f)
|
||||
|
|
|
@ -223,11 +223,12 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
|
|||
|
||||
wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
|
||||
wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
|
||||
wire srval;
|
||||
generate
|
||||
if (LSRMODE == "PRLD")
|
||||
wire srval = M;
|
||||
assign srval = M;
|
||||
else
|
||||
localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0;
|
||||
assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
|
||||
endgenerate
|
||||
|
||||
initial Q = srval;
|
||||
|
|
Loading…
Reference in New Issue