Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jim Lawson 2019-03-01 10:31:26 -08:00
commit 4cce7f6967
31 changed files with 622 additions and 105 deletions

View File

@ -169,7 +169,6 @@ struct FirrtlWorker
return *str == '\\' ? str + 1 : str;
}
std::string cellname(RTLIL::Cell *cell)
{
return fid(cell->name).c_str();
@ -219,29 +218,42 @@ struct FirrtlWorker
if (it->second.size() > 0) {
const SigSpec &secondSig = it->second;
const std::string firstName = cell_name + "." + make_id(it->first);
const std::string secondName = make_expr(secondSig);
const std::string secondExpr = make_expr(secondSig);
// Find the direction for this port.
FDirection dir = getPortFDirection(it->first, instModule);
std::string source, sink;
std::string sourceExpr, sinkExpr;
const SigSpec *sinkSig = nullptr;
switch (dir) {
case FD_INOUT:
log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second));
case FD_OUT:
source = firstName;
sink = secondName;
sourceExpr = firstName;
sinkExpr = secondExpr;
sinkSig = &secondSig;
break;
case FD_NODIRECTION:
log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second));
/* FALL_THROUGH */
case FD_IN:
source = secondName;
sink = firstName;
sourceExpr = secondExpr;
sinkExpr = firstName;
break;
default:
log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir);
break;
}
wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str()));
// Check for subfield assignment.
std::string bitsString = "bits(";
if (sinkExpr.substr(0, bitsString.length()) == bitsString ) {
if (sinkSig == nullptr)
log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str());
// Don't generate the assignment here.
// Add the source and sink to the "reverse_wire_map" and we'll output the assignment
// as part of the coalesced subfield assignments for this wire.
register_reverse_wire_map(sourceExpr, *sinkSig);
} else {
wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str()));
}
}
}
wire_exprs.push_back(stringf("\n"));

View File

@ -48,7 +48,7 @@ struct ProtobufDesignSerializer
ProtobufDesignSerializer(bool use_selection, bool aig_mode) :
aig_mode_(aig_mode), use_selection_(use_selection) { }
string get_name(IdString name)
{
return RTLIL::unescape_id(name);
@ -60,7 +60,7 @@ struct ProtobufDesignSerializer
{
for (auto &param : parameters) {
std::string key = get_name(param.first);
yosys::pb::Parameter pb_param;
@ -207,7 +207,7 @@ struct ProtobufDesignSerializer
(*models)[aig.name] = pb_model;
}
}
void serialize_design(yosys::pb::Design *pb, Design *design)
{
GOOGLE_PROTOBUF_VERIFY_VERSION;

View File

@ -1103,20 +1103,27 @@ struct Smt2Worker
break;
Const initword = init_data.extract(i*width, width, State::Sx);
Const initmask = initword;
bool gen_init_constr = false;
for (auto bit : initword.bits)
if (bit == State::S0 || bit == State::S1)
for (int k = 0; k < GetSize(initword); k++) {
if (initword[k] == State::S0 || initword[k] == State::S1) {
gen_init_constr = true;
initmask[k] = State::S1;
} else {
initmask[k] = State::S0;
initword[k] = State::S0;
}
}
if (gen_init_constr)
{
if (statebv)
/* FIXME */;
else
init_list.push_back(stringf("(= (select (|%s#%d#0| state) #b%s) #b%s) ; %s[%d]",
init_list.push_back(stringf("(= (bvand (select (|%s#%d#0| state) #b%s) #b%s) #b%s) ; %s[%d]",
get_id(module), arrayid, Const(i, abits).as_string().c_str(),
initword.as_string().c_str(), get_id(cell), i));
initmask.as_string().c_str(), initword.as_string().c_str(), get_id(cell), i));
}
}
}

View File

@ -33,7 +33,7 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal;
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal, siminit;
int auto_name_counter, auto_name_offset, auto_name_digits;
std::map<RTLIL::IdString, int> auto_name_map;
std::set<RTLIL::IdString> reg_wires, reg_ct;
@ -1310,7 +1310,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
}
}
if (reg_ct.count(cell->type) && cell->hasPort("\\Q")) {
if (siminit && reg_ct.count(cell->type) && cell->hasPort("\\Q")) {
std::stringstream ss;
dump_reg_init(ss, cell->getPort("\\Q"));
if (!ss.str().empty()) {
@ -1607,6 +1607,10 @@ struct VerilogBackend : public Backend {
log(" without this option all internal cells are converted to Verilog\n");
log(" expressions.\n");
log("\n");
log(" -siminit\n");
log(" add initial statements with hierarchical refs to initialize FFs when\n");
log(" in -noexpr mode.\n");
log("\n");
log(" -nodec\n");
log(" 32-bit constant values are by default dumped as decimal numbers,\n");
log(" not bit pattern. This option deactivates this feature and instead\n");
@ -1663,6 +1667,7 @@ struct VerilogBackend : public Backend {
nostr = false;
defparam = false;
decimal = false;
siminit = false;
auto_prefix = "";
bool blackboxes = false;
@ -1739,6 +1744,10 @@ struct VerilogBackend : public Backend {
decimal = true;
continue;
}
if (arg == "-siminit") {
siminit = true;
continue;
}
if (arg == "-blackboxes") {
blackboxes = true;
continue;

View File

@ -2316,7 +2316,7 @@ struct ReadPass : public Pass {
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
if (args.size() < 2)
if (args.size() < 2 || args[1][0] != '-')
log_cmd_error("Missing mode parameter.\n");
if (args.size() < 3)

View File

@ -1,12 +1,12 @@
//
// yosys -- Yosys Open SYnthesis Suite
//
//
// Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
//
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
@ -73,7 +73,7 @@ message Module {
BitVector bits = 2;
}
map<string, Port> port = 2;
// Named cells in this module.
message Cell {
// Set to true when the name of this cell is automatically created and
@ -129,7 +129,7 @@ message Model {
TYPE_FALSE = 6;
};
Type type = 1;
message Port {
// Name of port.
string portname = 1;
@ -148,7 +148,7 @@ message Model {
// Set for AND, NAND.
Gate gate = 3;
}
// Set when the node drives given output port(s).
message OutPort {
// Name of port.

View File

@ -53,6 +53,7 @@ struct WreduceWorker
std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells;
std::set<SigBit> work_queue_bits;
pool<SigBit> keep_bits;
dict<SigBit, State> init_bits;
WreduceWorker(WreduceConfig *config, Module *module) :
config(config), module(module), mi(module) { }
@ -141,6 +142,7 @@ struct WreduceWorker
SigSpec sig_d = mi.sigmap(cell->getPort("\\D"));
SigSpec sig_q = mi.sigmap(cell->getPort("\\Q"));
Const initval;
int width_before = GetSize(sig_q);
@ -150,16 +152,24 @@ struct WreduceWorker
bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0;
bool sign_ext = !zero_ext;
for (int i = 0; i < GetSize(sig_q); i++) {
SigBit bit = sig_q[i];
if (init_bits.count(bit))
initval.bits.push_back(init_bits.at(bit));
else
initval.bits.push_back(State::Sx);
}
for (int i = GetSize(sig_q)-1; i >= 0; i--)
{
if (zero_ext && sig_d[i] == State::S0) {
if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) {
module->connect(sig_q[i], State::S0);
sig_d.remove(i);
sig_q.remove(i);
continue;
}
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1]) {
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) {
module->connect(sig_q[i], sig_q[i-1]);
sig_d.remove(i);
sig_q.remove(i);
@ -167,7 +177,7 @@ struct WreduceWorker
}
auto info = mi.query(sig_q[i]);
if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) {
if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) {
sig_d.remove(i);
sig_q.remove(i);
zero_ext = false;
@ -183,10 +193,11 @@ struct WreduceWorker
if (GetSize(sig_q) == 0) {
log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type));
module->remove(cell);
return;
}
log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before,
log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before,
log_id(module), log_id(cell), log_id(cell->type));
for (auto bit : sig_d)
@ -376,10 +387,18 @@ struct WreduceWorker
void run()
{
for (auto w : module->wires())
for (auto w : module->wires()) {
if (w->get_bool_attribute("\\keep"))
for (auto bit : mi.sigmap(w))
keep_bits.insert(bit);
if (w->attributes.count("\\init")) {
Const initval = w->attributes.at("\\init");
SigSpec initsig = mi.sigmap(w);
int width = std::min(GetSize(initval), GetSize(initsig));
for (int i = 0; i < width; i++)
init_bits[initsig[i]] = initval[i];
}
}
for (auto c : module->selected_cells())
work_queue_cells.insert(c);

View File

@ -4,5 +4,5 @@ passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h
EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h
.SECONDARY: passes/pmgen/ice40_dsp_pm.h
passes/pmgen/ice40_dsp_pm.h: passes/pmgen/ice40_dsp.pmg passes/pmgen/pmgen.py
$(P) cd passes/pmgen && python3 pmgen.py ice40_dsp
passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg
$(P) mkdir -p passes/pmgen && python3 $^

View File

@ -6,7 +6,10 @@ import pprint
pp = pprint.PrettyPrinter(indent=4)
prefix = sys.argv[1]
pmgfile = sys.argv[1]
assert pmgfile.endswith(".pmg")
prefix = pmgfile[0:-4]
pmname = prefix.split('/')[-1]
state_types = dict()
udata_types = dict()
@ -73,7 +76,7 @@ def rewrite_cpp(s):
return "".join(t)
with open("%s.pmg" % prefix, "r") as f:
with open(pmgfile, "r") as f:
while True:
line = f.readline()
if line == "": break
@ -82,7 +85,7 @@ with open("%s.pmg" % prefix, "r") as f:
cmd = line.split()
if len(cmd) == 0 or cmd[0].startswith("//"): continue
cmd = cmd[0]
if cmd == "state":
m = re.match(r"^state\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line)
assert m
@ -187,10 +190,10 @@ with open("%s_pm.h" % prefix, "w") as f:
print("YOSYS_NAMESPACE_BEGIN", file=f)
print("", file=f)
print("struct {}_pm {{".format(prefix), file=f)
print("struct {}_pm {{".format(pmname), file=f)
print(" Module *module;", file=f)
print(" SigMap sigmap;", file=f)
print(" std::function<void()> on_accept;".format(prefix), file=f)
print(" std::function<void()> on_accept;".format(pmname), file=f)
print("", file=f)
for index in range(len(blocks)):
@ -288,7 +291,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(prefix), file=f)
print(" {}_pm(Module *module, const vector<Cell*> &cells) :".format(pmname), file=f)
print(" module(module), sigmap(module) {", file=f)
for s, t in sorted(udata_types.items()):
if t.endswith("*"):
@ -318,7 +321,7 @@ with open("%s_pm.h" % prefix, "w") as f:
print(" }", file=f)
print("", file=f)
print(" ~{}_pm() {{".format(prefix), file=f)
print(" ~{}_pm() {{".format(pmname), file=f)
print(" for (auto cell : autoremove_cells)", file=f)
print(" module->remove(cell);", file=f)
print(" }", file=f)
@ -337,7 +340,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(prefix), file=f)
print(" void run(std::function<void({}_pm&)> on_accept_f) {{".format(pmname), file=f)
print(" run([&](){on_accept_f(*this);});", file=f)
print(" }", file=f)
print("", file=f)

View File

@ -8,4 +8,5 @@ OBJS += passes/sat/expose.o
OBJS += passes/sat/assertpmux.o
OBJS += passes/sat/clk2fflogic.o
OBJS += passes/sat/async2sync.o
OBJS += passes/sat/supercover.o

92
passes/sat/supercover.cc Normal file
View File

@ -0,0 +1,92 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct SupercoverPass : public Pass {
SupercoverPass() : Pass("supercover", "add hi/lo cover cells for each wire bit") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" supercover [options] [selection]\n");
log("\n");
log("This command adds two cover cells for each bit of each selected wire, one\n");
log("checking for a hi signal level and one checking for lo level.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
// bool flag_noinit = false;
log_header(design, "Executing SUPERCOVER pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
// if (args[argidx] == "-noinit") {
// flag_noinit = true;
// continue;
// }
break;
}
extra_args(args, argidx, design);
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
pool<SigBit> handled_bits;
int cnt_wire = 0, cnt_bits = 0;
log("Adding cover cells to module %s.\n", log_id(module));
for (auto wire : module->selected_wires())
{
bool counted_wire = false;
std::string src = wire->get_src_attribute();
for (auto bit : sigmap(SigSpec(wire)))
{
if (bit.wire == nullptr)
continue;
if (handled_bits.count(bit))
continue;
SigSpec inv = module->Not(NEW_ID, bit);
module->addCover(NEW_ID, bit, State::S1, src);
module->addCover(NEW_ID, inv, State::S1, src);
handled_bits.insert(bit);
if (!counted_wire) {
counted_wire = false;
cnt_wire++;
}
cnt_bits++;
}
}
log(" added cover cells to %d wires, %d bits.\n", cnt_wire, cnt_bits);
}
}
} SupercoverPass;
PRIVATE_NAMESPACE_END

View File

@ -660,8 +660,8 @@ struct DfflibmapPass : public Pass {
map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_");
map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_");
log(" final dff cell mappings:\n");
logmap_all();
log(" final dff cell mappings:\n");
logmap_all();
for (auto &it : design->modules_)
if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox"))

View File

@ -132,9 +132,9 @@ static void dump_dot_graph(string filename,
pool<RTLIL::SigBit> nodes, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> edges,
pool<RTLIL::SigBit> inputs, pool<RTLIL::SigBit> outputs,
std::function<GraphStyle(RTLIL::SigBit)> node_style =
[](RTLIL::SigBit) { return GraphStyle{}; },
[](RTLIL::SigBit) { return GraphStyle{}; },
std::function<GraphStyle(RTLIL::SigBit, RTLIL::SigBit)> edge_style =
[](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; },
[](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; },
string name = "")
{
FILE *f = fopen(filename.c_str(), "w");

View File

@ -30,7 +30,7 @@ endmodule
module PADOUT (output padout, input padin, input oe);
assign padout = padin;
assign oe = oe;
endmodule
endmodule
module LUT4 (output dout,
input din0, din1, din2, din3);
@ -66,14 +66,14 @@ always @(dataa_w or datab_w or datac_w or datad_w) begin
datac_w, datad_w);
end
assign dout = combout_rt & 1'b1;
endmodule
endmodule
module DFF (output q,
input d, ck);
reg q;
always @(posedge ck)
q <= d;
endmodule

View File

@ -52,13 +52,13 @@ struct AnlogicEqnPass : public Pass {
eqn += names[j];
else
eqn += std::string("~") + names[j];
if (j!=(inputs-1)) eqn += "*";
}
eqn += ")+";
}
}
if (eqn.empty()) return Const("0");
if (eqn.empty()) return Const("0");
eqn = eqn.substr(0, eqn.length()-1);
return Const(eqn);
}

View File

@ -1,5 +1,5 @@
OBJS += techlibs/ecp5/synth_ecp5.o
OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))

View File

@ -33,7 +33,7 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO);
input CI, BI;
output [Y_WIDTH-1:0] CO;
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
wire [Y_WIDTH-1:0] A_buf, B_buf;
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));

View File

@ -156,6 +156,41 @@ module OSCG(
parameter DIV = 128;
endmodule
(* blackbox *) (* keep *)
module USRMCLK(
input USRMCLKI, USRMCLKTS,
output USRMCLKO
);
endmodule
(* blackbox *) (* keep *)
module JTAGG(
input TCK, TMS, TDI, JTDO2, JTDO1,
output TDO, JTDI, JTCK, JRTI2, JRTI1,
output JSHIFT, JUPDATE, JRSTN, JCE2, JCE1
);
parameter ER1 = "ENABLED";
parameter ER2 = "ENABLED";
endmodule
(* blackbox *)
module DELAYF(
input A, LOADN, MOVE, DIRECTION,
output Z, CFLAG
);
parameter DEL_MODE = "USER_DEFINED";
parameter DEL_VALUE = 0;
endmodule
(* blackbox *)
module DELAYG(
input A,
output Z
);
parameter DEL_MODE = "USER_DEFINED";
parameter DEL_VALUE = 0;
endmodule
(* blackbox *)
module IDDRX1F(
input D, SCLK, RST,
@ -164,6 +199,31 @@ module IDDRX1F(
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module IDDRX2F(
input D, SCLK, ECLK, RST,
output Q0, Q1, Q2, Q3
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module IDDR71B(
input D, SCLK, ECLK, RST, ALIGNWD,
output Q0, Q1, Q2, Q3, Q4, Q5, Q6
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module IDDRX2DQA(
input D, DQSR90, ECLK, SCLK, RST,
input RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0,
output Q0, Q1, Q2, Q3, QWL
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module ODDRX1F(
input SCLK, RST, D0, D1,
@ -172,6 +232,91 @@ module ODDRX1F(
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module ODDRX2F(
input SCLK, ECLK, RST, D0, D1, D2, D3,
output Q
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module ODDR71B(
input SCLK, ECLK, RST, D0, D1, D2, D3, D4, D5, D6,
output Q
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module OSHX2A(
input D0, D1, RST, ECLK, SCLK,
output Q
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module ODDRX2DQA(
input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW270,
output Q
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module ODDRX2DQSB(
input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW,
output Q
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module TSHX2DQA(
input T0, T1, SCLK, ECLK, DQSW270, RST,
output Q
);
parameter GSR = "ENABLED";
parameter REGSET = "SET";
endmodule
(* blackbox *)
module TSHX2DQSA(
input T0, T1, SCLK, ECLK, DQSW, RST,
output Q
);
parameter GSR = "ENABLED";
parameter REGSET = "SET";
endmodule
(* blackbox *)
module DQSBUFM(
input DQSI, READ1, READ0, READCLKSEL2, READCLKSEL1, READCLKSEL0, DDRDEL,
input ECLK, SCLK,
input DYNDELAY7, DYNDELAY6, DYNDELAY5, DYNDELAY4,
input DYNDELAY3, DYNDELAY2, DYNDELAY1, DYNDELAY0,
input RST, RDLOADN, RDMOVE, RDDIRECTION, WRLOADN, WRMOVE, WRDIRECTION, PAUSE,
output DQSR90, DQSW, DQSW270,
output RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0,
output DATAVALID, BURSTDET, RDCFLAG, WRCFLAG
);
parameter DQS_LI_DEL_ADJ = "FACTORYONLY";
parameter DQS_LI_DEL_VAL = 0;
parameter DQS_LO_DEL_ADJ = "FACTORYONLY";
parameter DQS_LO_DEL_VAL = 0;
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module DDRDLLA(
input CLK, RST, UDDCNTLN, FREEZE,
output LOCK, DDRDEL, DCNTL7, DCNTL6, DCNTL5, DCNTL4, DCNTL3, DCNTL2, DCNTL1, DCNTL0
);
parameter FORCE_MAX_DELAY = "NO";
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module CLKDIVF(
input CLKI, RST, ALIGNWD,
@ -181,6 +326,13 @@ module CLKDIVF(
parameter DIV = "2.0";
endmodule
(* blackbox *)
module ECLKSYNCB(
input ECLKI, STOP,
output ECLKO
);
endmodule
(* blackbox *)
module DCCA(
input CLKI, CE,

View File

@ -47,6 +47,9 @@ module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"
module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
// For Diamond compatibility, FIXME: add all Diamond flipflop mappings
module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
`ifndef NO_LUT
module \$lut (A, Y);
parameter WIDTH = 0;

View File

@ -57,7 +57,7 @@ module TRELLIS_RAM16X2 (
input RAD0, RAD1, RAD2, RAD3,
output DO0, DO1
);
parameter WCKMUX = "WCK";
parameter WCKMUX = "WCK";
parameter WREMUX = "WRE";
parameter INITVAL_0 = 16'h0000;
parameter INITVAL_1 = 16'h0000;
@ -104,7 +104,7 @@ module TRELLIS_DPR16X4 (
input [3:0] RAD,
output [3:0] DO
);
parameter WCKMUX = "WCK";
parameter WCKMUX = "WCK";
parameter WREMUX = "WRE";
parameter [63:0] INITVAL = 64'h0000000000000000;
@ -203,13 +203,14 @@ endmodule
// ---------------------------------------
module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q);
module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
parameter GSR = "ENABLED";
parameter [127:0] CEMUX = "1";
parameter CLKMUX = "CLK";
parameter LSRMUX = "LSR";
parameter SRMODE = "LSR_OVER_CE";
parameter REGSET = "RESET";
parameter [127:0] LSRMODE = "LSR";
reg muxce;
always @(*)
@ -222,8 +223,12 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q);
wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0;
generate
if (LSRMODE == "PRLD")
wire srval = M;
else
localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0;
endgenerate
initial Q = srval;
@ -339,6 +344,8 @@ module TRELLIS_SLICE(
parameter REG1_SD = "0";
parameter REG0_REGSET = "RESET";
parameter REG1_REGSET = "RESET";
parameter REG0_LSRMODE = "LSR";
parameter REG1_LSRMODE = "LSR";
parameter [127:0] CCU2_INJECT1_0 = "NO";
parameter [127:0] CCU2_INJECT1_1 = "NO";
parameter WREMUX = "WRE";
@ -428,10 +435,11 @@ module TRELLIS_SLICE(
.CLKMUX(CLKMUX),
.LSRMUX(LSRMUX),
.SRMODE(SRMODE),
.REGSET(REG0_REGSET)
.REGSET(REG0_REGSET),
.LSRMODE(REG0_LSRMODE)
) ff_0 (
.CLK(CLK), .LSR(LSR), .CE(CE),
.DI(muxdi0),
.DI(muxdi0), .M(M0),
.Q(Q0)
);
TRELLIS_FF #(
@ -440,10 +448,11 @@ module TRELLIS_SLICE(
.CLKMUX(CLKMUX),
.LSRMUX(LSRMUX),
.SRMODE(SRMODE),
.REGSET(REG1_REGSET)
.REGSET(REG1_REGSET),
.LSRMODE(REG1_LSRMODE)
) ff_1 (
.CLK(CLK), .LSR(LSR), .CE(CE),
.DI(muxdi1),
.DI(muxdi1), .M(M1),
.Q(Q1)
);
endmodule
@ -547,3 +556,20 @@ module DP16KD(
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
endmodule
// For Diamond compatibility, FIXME: add all Diamond flipflop mappings
module FD1S3BX(input PD, D, CK, output Q);
TRELLIS_FF #(
.GSR("DISABLED"),
.CEMUX("1"),
.CLKMUX("CLK"),
.LSRMUX("LSR"),
.REGSET("SET"),
.SRMODE("ASYNC")
) tff_i (
.CLK(CK),
.LSR(PD),
.DI(D),
.Q(Q)
);
endmodule

View File

@ -0,0 +1,198 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
* Copyright (C) 2018-19 David Shah <david@symbioticeda.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct Ecp5FfinitPass : public Pass {
Ecp5FfinitPass() : Pass("ecp5_ffinit", "ECP5: handle FF init values") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" ecp5_ffinit [options] [selection]\n");
log("\n");
log("Remove init values for FF output signals when equal to reset value.\n");
log("If reset is not used, set the reset value to the init value, otherwise\n");
log("unmap out the reset (if not an async reset).\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ECP5_FFINIT pass (implement FF init values).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
// if (args[argidx] == "-singleton") {
// singleton_mode = true;
// continue;
// }
break;
}
extra_args(args, argidx, design);
for (auto module : design->selected_modules())
{
log("Handling FF init values in %s.\n", log_id(module));
SigMap sigmap(module);
pool<Wire*> init_wires;
dict<SigBit, State> initbits;
dict<SigBit, SigBit> initbit_to_wire;
pool<SigBit> handled_initbits;
for (auto wire : module->selected_wires())
{
if (wire->attributes.count("\\init") == 0)
continue;
SigSpec wirebits = sigmap(wire);
Const initval = wire->attributes.at("\\init");
init_wires.insert(wire);
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
{
SigBit bit = wirebits[i];
State val = initval[i];
if (val != State::S0 && val != State::S1)
continue;
if (initbits.count(bit)) {
if (initbits.at(bit) != val)
log_error("Conflicting init values for signal %s (%s = %s, %s = %s).\n",
log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val),
log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit)));
continue;
}
initbits[bit] = val;
initbit_to_wire[bit] = SigBit(wire, i);
}
}
for (auto cell : module->selected_cells())
{
if (cell->type != "\\TRELLIS_FF")
continue;
SigSpec sig_d = cell->getPort("\\DI");
SigSpec sig_q = cell->getPort("\\Q");
SigSpec sig_lsr = cell->getPort("\\LSR");
if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
continue;
SigBit bit_d = sigmap(sig_d[0]);
SigBit bit_q = sigmap(sig_q[0]);
std::string regset = "RESET";
if (cell->hasParam("\\REGSET"))
regset = cell->getParam("\\REGSET").decode_string();
State resetState;
if (regset == "SET")
resetState = State::S1;
else if (regset == "RESET")
resetState = State::S0;
else
log_error("FF cell %s has illegal REGSET value %s.\n",
log_id(cell), regset.c_str());
if (!initbits.count(bit_q))
continue;
State val = initbits.at(bit_q);
log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type),
log_signal(bit_q), val != State::S0 ? '1' : '0');
// Initval is the same as the reset state. Matches hardware, nowt more to do
if (val == resetState) {
handled_initbits.insert(bit_q);
continue;
}
if (GetSize(sig_lsr) >= 1 && sig_lsr[0] != State::S0) {
std::string srmode = "LSR_OVER_CE";
if (cell->hasParam("\\SRMODE"))
srmode = cell->getParam("\\SRMODE").decode_string();
if (srmode == "ASYNC") {
log("Async reset value %c for FF cell %s inconsistent with init value %c.\n",
resetState != State::S0 ? '1' : '0', log_id(cell), val != State::S0 ? '1' : '0');
} else {
SigBit bit_lsr = sigmap(sig_lsr[0]);
Wire *new_bit_d = module->addWire(NEW_ID);
if (resetState == State::S0) {
module->addAndnotGate(NEW_ID, bit_d, bit_lsr, new_bit_d);
} else {
module->addOrGate(NEW_ID, bit_d, bit_lsr, new_bit_d);
}
cell->setPort("\\DI", new_bit_d);
cell->setPort("\\LSR", State::S0);
if(cell->hasPort("\\CE")) {
std::string cemux = "CE";
if (cell->hasParam("\\CEMUX"))
cemux = cell->getParam("\\CEMUX").decode_string();
SigSpec sig_ce = cell->getPort("\\CE");
if (GetSize(sig_ce) >= 1) {
SigBit bit_ce = sigmap(sig_ce[0]);
Wire *new_bit_ce = module->addWire(NEW_ID);
if (cemux == "INV")
module->addAndnotGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce);
else
module->addOrGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce);
cell->setPort("\\CE", new_bit_ce);
}
}
cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET"));
handled_initbits.insert(bit_q);
}
} else {
cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET"));
handled_initbits.insert(bit_q);
}
}
for (auto wire : init_wires)
{
if (wire->attributes.count("\\init") == 0)
continue;
SigSpec wirebits = sigmap(wire);
Const &initval = wire->attributes.at("\\init");
bool remove_attribute = true;
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) {
if (handled_initbits.count(wirebits[i]))
initval[i] = State::Sx;
else if (initval[i] != State::Sx)
remove_attribute = false;
}
if (remove_attribute)
wire->attributes.erase("\\init");
}
}
}
} Ecp5FfinitPass;
PRIVATE_NAMESPACE_END

View File

@ -255,10 +255,7 @@ struct SynthEcp5Pass : public ScriptPass
run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
run("opt_expr -mux_undef");
run("simplemap");
// TODO
#if 0
run("ecp5_ffinit");
#endif
}
if (check_label("map_luts"))

View File

@ -25,24 +25,24 @@ module _80_gw1n_alu(A, B, CI, BI, X, Y, CO);
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
output [Y_WIDTH-1:0] X, Y;
input CI, BI;
output [Y_WIDTH-1:0] CO;
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
wire [Y_WIDTH-1:0] A_buf, B_buf;
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
wire [Y_WIDTH-1:0] AA = A_buf;
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
wire [Y_WIDTH-1:0] C = {CO, CI};
genvar i;
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
ALU #(.ALU_MODE(32'b0))

View File

@ -111,7 +111,7 @@ struct SynthGowinPass : public ScriptPass
if (args[argidx] == "-noflatten") {
flatten = false;
continue;
}
}
break;
}
extra_args(args, argidx, design);

View File

@ -112,14 +112,14 @@ module GP_OBUFT(input IN, input OE, output OUT);
endmodule
module \$lut (A, Y);
parameter WIDTH = 0;
parameter LUT = 0;
parameter WIDTH = 0;
parameter LUT = 0;
input [WIDTH-1:0] A;
output Y;
input [WIDTH-1:0] A;
output Y;
generate
if (WIDTH == 1) begin
generate
if (WIDTH == 1) begin
if(LUT == 2'b01) begin
GP_INV _TECHMAP_REPLACE_ (.OUT(Y), .IN(A[0]) );
end
@ -127,22 +127,22 @@ module \$lut (A, Y);
GP_2LUT #(.INIT({2'b00, LUT})) _TECHMAP_REPLACE_ (.OUT(Y),
.IN0(A[0]), .IN1(1'b0));
end
end else
if (WIDTH == 2) begin
GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
.IN0(A[0]), .IN1(A[1]));
end else
if (WIDTH == 3) begin
GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]));
end else
if (WIDTH == 4) begin
GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3]));
end else begin
wire _TECHMAP_FAIL_ = 1;
end
endgenerate
end else
if (WIDTH == 2) begin
GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
.IN0(A[0]), .IN1(A[1]));
end else
if (WIDTH == 3) begin
GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]));
end else
if (WIDTH == 4) begin
GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3]));
end else begin
wire _TECHMAP_FAIL_ = 1;
end
endgenerate
endmodule
module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP);

View File

@ -7,8 +7,8 @@ module \$__ICE40_RAM4K (
input [10:0] WADDR,
input [15:0] MASK, WDATA
);
parameter integer READ_MODE = 0;
parameter integer WRITE_MODE = 0;
parameter [1:0] READ_MODE = 0;
parameter [1:0] WRITE_MODE = 0;
parameter [0:0] NEGCLK_R = 0;
parameter [0:0] NEGCLK_W = 0;

View File

@ -32,7 +32,7 @@ module fa
wire VCC;
assign VCC = 1'b1;
cycloneiv_lcell_comb gen_sum_0 (.combout(sum_x),
.dataa(a_c),
.datab(b_c),
@ -40,7 +40,7 @@ module fa
.datad(VCC));
defparam syn__05_.lut_mask = 16'b1001011010010110;
defparam syn__05_.sum_lutc_input = "datac";
cycloneiv_lcell_comb gen_cout_0 (.combout(cout_t),
.dataa(cin_c),
.datab(b_c),
@ -48,11 +48,11 @@ module fa
.datad(VCC));
defparam syn__06_.lut_mask = 16'b1110000011100000;
defparam syn__06_.sum_lutc_input = "datac";
endmodule // fa
module f_stage();
endmodule // f_stage
module f_end();
@ -88,7 +88,7 @@ module _80_cycloneive_alu (A, B, CI, BI, X, Y, CO);
.cin_c(C[0]),
.cout_t(C0[1]),
.sum_x(Y[0]));
genvar i;
generate for (i = 1; i < Y_WIDTH; i = i + 1) begin:slice
cycloneive_lcell_comb #(.lut_mask(16'b0101_1010_0101_0000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(CO[i]), .dataa(BB[i]), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[i]));

View File

@ -76,7 +76,7 @@ module \$lut (A, Y);
wire VCC;
wire GND;
assign {VCC,GND} = {1'b1,1'b0};
generate
if (WIDTH == 1) begin
assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
@ -151,7 +151,7 @@ module \$lut (A, Y);
TODO: There's not a just 7-input function on Cyclone V, see the following note:
**Extended LUT Mode**
Use extended LUT mode to implement a specific set of 7-input functions. The set must
be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs.
be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs.
[source](Device Interfaces and Integration Basics for Cyclone V Devices).
end*/
else

View File

@ -6,7 +6,6 @@ code_hdl_models_d_latch_gates.v combinational loop
code_hdl_models_dff_async_reset.v $adff
code_hdl_models_tff_async_reset.v $adff
code_hdl_models_uart.v $adff
code_specman_switch_fabric.v subfield assignment (bits() <= ...)
code_tidbits_asyn_reset.v $adff
code_tidbits_reg_seq_example.v $adff
code_verilog_tutorial_always_example.v empty module

View File

@ -12,7 +12,6 @@ multiplier.v inst id[0] of
muxtree.v drops modules
omsp_dbg_uart.v $adff
operators.v $pow
paramods.v subfield assignment (bits() <= ...)
partsel.v drops modules
process.v drops modules
realexpr.v drops modules

View File

@ -8,7 +8,7 @@ verbose=false
keeprunning=false
makejmode=false
frontend="verilog"
backend_opts="-noattr -noexpr"
backend_opts="-noattr -noexpr -siminit"
autotb_opts=""
include_opts=""
xinclude_opts=""
@ -49,7 +49,7 @@ while getopts xmGl:wkjvref:s:p:n:S:I:-: opt; do
r)
backend_opts="$backend_opts -norename" ;;
e)
backend_opts="$( echo " $backend_opts " | sed 's, -noexpr ,,; s,^ ,,; s, $,,;'; )" ;;
backend_opts="$( echo " $backend_opts " | sed 's, -noexpr , ,; s,^ ,,; s, $,,;'; )" ;;
f)
frontend="$OPTARG" ;;
s)
@ -175,7 +175,7 @@ do
if [ -n "$firrtl2verilog" ]; then
if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then
"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v
$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v -X verilog
$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v
test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v
fi
fi