Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jim Lawson 2019-03-04 12:55:02 -08:00
commit 6d2ea6fe55
12 changed files with 124 additions and 28 deletions

View File

@ -132,11 +132,11 @@ matrix:
env: env:
- MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0" - MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0"
# Latest clang on Mac OS X # # Latest clang on Mac OS X
- os: osx # - os: osx
osx_image: xcode9.4 # osx_image: xcode9.4
env: # env:
- MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++" # - MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++"
before_install: before_install:
- ./.travis/setup.sh - ./.travis/setup.sh

View File

@ -34,11 +34,24 @@ compatible license that is similar in terms to the MIT license
or the 2-clause BSD 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: 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 Setup
====== ======
@ -296,6 +309,9 @@ Verilog Attributes and non-standard features
passes to identify input and output ports of cells. The Verilog backend passes to identify input and output ports of cells. The Verilog backend
also does not output blackbox modules on default. 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 - 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 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. have hidden connections that are not part of the netlist, such as IO pads.

View File

@ -130,7 +130,7 @@ struct EdifBackend : public Backend {
bool port_rename = false; bool port_rename = false;
bool attr_properties = false; bool attr_properties = false;
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports; 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); CellTypes ct(design);
EdifNames edif_names; EdifNames edif_names;

View File

@ -15,6 +15,7 @@ new_project \
import_files -hdl_source {netlist.vm} import_files -hdl_source {netlist.vm}
import_files -sdc {example.sdc} import_files -sdc {example.sdc}
import_files -io_pdc {example.pdc} import_files -io_pdc {example.pdc}
build_design_hierarchy
set_option -synth 0 set_option -synth 0
organize_tool_files -tool PLACEROUTE \ organize_tool_files -tool PLACEROUTE \
@ -32,22 +33,25 @@ configure_tool -name PLACEROUTE \
-params EFFORT_LEVEL:false \ -params EFFORT_LEVEL:false \
-params REPAIR_MIN_DELAY:false -params REPAIR_MIN_DELAY:false
puts ""
puts "**> COMPILE" puts "**> COMPILE"
run_tool -name {COMPILE} run_tool -name {COMPILE}
puts "<** COMPILE" puts "<** COMPILE"
puts ""
puts "**> PLACEROUTE" puts "**> PLACEROUTE"
run_tool -name {PLACEROUTE} run_tool -name {PLACEROUTE}
puts "<** PLACEROUTE" puts "<** PLACEROUTE"
puts ""
puts "**> VERIFYTIMING" puts "**> VERIFYTIMING"
run_tool -name {VERIFYTIMING} run_tool -name {VERIFYTIMING}
puts "<** VERIFYTIMING" puts "<** VERIFYTIMING"
save_project puts ""
puts "**> BITSTREAM"
# puts "**> export_bitstream" export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC}
# export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC} puts "<** BITSTREAM"
# puts "<** export_bitstream"
puts ""
exit 0 exit 0

View File

@ -1,4 +1,6 @@
#!/bin/bash #!/bin/bash
set -ex set -ex
yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v 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 .

View File

@ -214,6 +214,8 @@ namespace AST
MEM2REG_FL_SET_ASYNC = 0x00000800, MEM2REG_FL_SET_ASYNC = 0x00000800,
MEM2REG_FL_EQ2 = 0x00001000, MEM2REG_FL_EQ2 = 0x00001000,
MEM2REG_FL_CMPLX_LHS = 0x00002000, MEM2REG_FL_CMPLX_LHS = 0x00002000,
MEM2REG_FL_CONST_LHS = 0x00004000,
MEM2REG_FL_VAR_LHS = 0x00008000,
/* proc flags */ /* proc flags */
MEM2REG_FL_EQ1 = 0x01000000, MEM2REG_FL_EQ1 = 0x01000000,
@ -237,6 +239,7 @@ namespace AST
bool has_const_only_constructs(bool &recommend_const_eval); bool has_const_only_constructs(bool &recommend_const_eval);
void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall); void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);
AstNode *eval_const_function(AstNode *fcall); AstNode *eval_const_function(AstNode *fcall);
bool is_simple_const_expr();
// create a human-readable text representation of the AST (for debugging) // create a human-readable text representation of the AST (for debugging)
void dumpAst(FILE *f, std::string indent) const; void dumpAst(FILE *f, std::string indent) const;

View File

@ -544,7 +544,11 @@ struct AST_INTERNAL::ProcessGenerator
break; break;
case AST_WIRE: 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; break;
case AST_PARAMETER: case AST_PARAMETER:

View File

@ -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) if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS)
goto verbose_activate; 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)); // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
continue; 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++) { for (size_t i = 0; i < children.size(); i++) {
AstNode *node = children[i]; AstNode *node = children[i];
if (node->type == AST_WIRE) { 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) { if (this_wire_scope.count(node->str) > 0) {
AstNode *first_node = this_wire_scope[node->str]; AstNode *first_node = this_wire_scope[node->str];
if (first_node->is_input && node->is_reg) 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 (current_scope.count(str) == 0) {
if (flag_autowire) { if (flag_autowire || str == "\\$global_clock") {
AstNode *auto_wire = new AstNode(AST_AUTOWIRE); AstNode *auto_wire = new AstNode(AST_AUTOWIRE);
auto_wire->str = str; auto_wire->str = str;
current_ast_mod->children.push_back(auto_wire); 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); 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; 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; 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 // remember where this is
if (flags & MEM2REG_FL_INIT) { if (flags & MEM2REG_FL_INIT) {
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_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) if (type == AST_FUNCTION || type == AST_TASK)
return false; 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 (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set))
{ {
if (async_block == NULL) { if (async_block == NULL) {
@ -3277,6 +3332,16 @@ bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
return false; 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() // helper function for AstNode::eval_const_function()
void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall) void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall)
{ {

View File

@ -910,7 +910,7 @@ struct HierarchyPass : public Pass {
if (m == nullptr) if (m == nullptr)
continue; 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); IdString new_m_name = m->derive(design, cell->parameters, true);
if (new_m_name.empty()) if (new_m_name.empty())
continue; continue;

View File

@ -5,4 +5,4 @@ EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h
.SECONDARY: 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 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 $^ $@

View File

@ -9,7 +9,8 @@ pp = pprint.PrettyPrinter(indent=4)
pmgfile = sys.argv[1] pmgfile = sys.argv[1]
assert pmgfile.endswith(".pmg") assert pmgfile.endswith(".pmg")
prefix = pmgfile[0:-4] prefix = pmgfile[0:-4]
pmname = prefix.split('/')[-1] prefix = prefix.split('/')[-1]
outfile = sys.argv[2]
state_types = dict() state_types = dict()
udata_types = dict() udata_types = dict()
@ -179,7 +180,7 @@ with open(pmgfile, "r") as f:
blocks.append(block) 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("// Generated by pmgen.py from {}.pgm".format(prefix), file=f)
print("", 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("YOSYS_NAMESPACE_BEGIN", file=f)
print("", 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(" Module *module;", file=f)
print(" SigMap sigmap;", 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) print("", file=f)
for index in range(len(blocks)): 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("", 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) print(" module(module), sigmap(module) {", file=f)
for s, t in sorted(udata_types.items()): for s, t in sorted(udata_types.items()):
if t.endswith("*"): if t.endswith("*"):
@ -321,7 +322,7 @@ with open("%s_pm.h" % prefix, "w") as f:
print(" }", file=f) print(" }", file=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(" for (auto cell : autoremove_cells)", file=f)
print(" module->remove(cell);", file=f) print(" module->remove(cell);", file=f)
print(" }", 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("", 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(" run([&](){on_accept_f(*this);});", file=f)
print(" }", file=f) print(" }", file=f)
print("", file=f) print("", file=f)

View File

@ -223,11 +223,12 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR; wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK; wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
wire srval;
generate generate
if (LSRMODE == "PRLD") if (LSRMODE == "PRLD")
wire srval = M; assign srval = M;
else else
localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0; assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
endgenerate endgenerate
initial Q = srval; initial Q = srval;