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:
- 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

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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 .

View File

@ -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;

View File

@ -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:

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)
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)
{

View File

@ -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;

View File

@ -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 $^ $@

View File

@ -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)

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 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;