diff options
25 files changed, 156 insertions, 313 deletions
diff --git a/backends/cxxrtl/cxxrtl_capi.cc b/backends/cxxrtl/cxxrtl_capi.cc index e0566e152..b77e4c491 100644 --- a/backends/cxxrtl/cxxrtl_capi.cc +++ b/backends/cxxrtl/cxxrtl_capi.cc @@ -43,6 +43,14 @@ void cxxrtl_destroy(cxxrtl_handle handle) { delete handle; } +int cxxrtl_eval(cxxrtl_handle handle) { + return handle->module->eval(); +} + +int cxxrtl_commit(cxxrtl_handle handle) { + return handle->module->commit(); +} + size_t cxxrtl_step(cxxrtl_handle handle) { return handle->module->step(); } diff --git a/backends/cxxrtl/cxxrtl_capi.h b/backends/cxxrtl/cxxrtl_capi.h index 599284898..74257f0da 100644 --- a/backends/cxxrtl/cxxrtl_capi.h +++ b/backends/cxxrtl/cxxrtl_capi.h @@ -55,6 +55,18 @@ cxxrtl_handle cxxrtl_create(cxxrtl_toplevel design); // Release all resources used by a design and its handle. void cxxrtl_destroy(cxxrtl_handle handle); +// Evaluate the design, propagating changes on inputs to the `next` value of internal state and +// output wires. +// +// Returns 1 if the design is known to immediately converge, 0 otherwise. +int cxxrtl_eval(cxxrtl_handle handle); + +// Commit the design, replacing the `curr` value of internal state and output wires with the `next` +// value. +// +// Return 1 if any of the `curr` values, 0 otherwise. +int cxxrtl_commit(cxxrtl_handle handle); + // Simulate the design to a fixed point. // // Returns the number of delta cycles. diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index c4df5c0a0..00f8c8df6 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -4231,6 +4231,8 @@ bool AstNode::detect_latch(const std::string &var) case AST_POSEDGE: case AST_NEGEDGE: return false; + case AST_EDGE: + break; case AST_BLOCK: if (!c->detect_latch(var)) return false; diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index f03faa9cf..9086943dc 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -173,9 +173,7 @@ struct OptMergeWorker for (const auto &it : cell1->connections_) { if (cell1->output(it.first)) { - if (it.first == ID::Q && (cell1->type.begins_with("$dff") || cell1->type.begins_with("$dlatch") || - cell1->type.begins_with("$_DFF") || cell1->type.begins_with("$_DLATCH") || cell1->type.begins_with("$_SR_") || - cell1->type.in(ID($adff), ID($sr), ID($ff), ID($_FF_)))) { + if (it.first == ID::Q && RTLIL::builtin_ff_cell_types().count(cell1->type)) { // For the 'Q' output of state elements, // use the (* init *) attribute value auto &sig1 = conn1[it.first]; diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc index e7c8a80dd..3ed158f37 100644 --- a/passes/proc/proc_dlatch.cc +++ b/passes/proc/proc_dlatch.cc @@ -37,6 +37,7 @@ struct proc_dlatch_db_t dict<Cell*, vector<SigBit>> mux_srcbits; dict<SigBit, pair<Cell*, int>> mux_drivers; dict<SigBit, int> sigusers; + dict<SigBit, std::pair<State,SigBit>> initbits; proc_dlatch_db_t(Module *module) : module(module), sigmap(module) { @@ -69,9 +70,34 @@ struct proc_dlatch_db_t } for (auto wire : module->wires()) + { if (wire->port_input) for (auto bit : sigmap(wire)) sigusers[bit]++; + if (wire->attributes.count(ID::init)) { + SigSpec wirebits = sigmap(wire); + Const initval = wire->attributes.at(ID::init); + + 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 && bit.wire != nullptr) + continue; + + if (initbits.count(bit)) { + if (initbits.at(bit).first != val) + log_error("Conflicting init values for signal %s (%s = %s != %s).\n", + log_signal(bit), log_signal(SigBit(wire, i)), + log_signal(val), log_signal(initbits.at(bit).first)); + continue; + } + + initbits[bit] = std::make_pair(val,SigBit(wire,i)); + } + } + } } bool quickcheck(const SigSpec &haystack, const SigSpec &needle) @@ -393,6 +419,13 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) else log("No latch inferred for signal `%s.%s' from process `%s.%s'.\n", db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str()); + for (auto &bit : lhs) { + auto it = db.initbits.find(bit); + if (it != db.initbits.end()) { + log("Removing init bit %s for non-memory siginal `%s.%s` in process `%s.%s`.\n", log_signal(it->second.first), db.module->name.c_str(), log_signal(bit), db.module->name.c_str(), proc->name.c_str()); + it->second.second.wire->attributes.at(ID::init)[it->second.second.offset] = State::Sx; + } + } db.module->connect(lhs, rhs); offset += chunk.width; } diff --git a/passes/techmap/dfflegalize.cc b/passes/techmap/dfflegalize.cc index c0f112836..13ce4f49a 100644 --- a/passes/techmap/dfflegalize.cc +++ b/passes/techmap/dfflegalize.cc @@ -1296,7 +1296,7 @@ unrecognized: sigmap.set(module); initbits.clear(); - for (auto wire : module->selected_wires()) + for (auto wire : module->wires()) { if (wire->attributes.count(ID::init) == 0) continue; diff --git a/techlibs/achronix/synth_achronix.cc b/techlibs/achronix/synth_achronix.cc index ddd9822b9..b203828d2 100644 --- a/techlibs/achronix/synth_achronix.cc +++ b/techlibs/achronix/synth_achronix.cc @@ -144,12 +144,12 @@ struct SynthAchronixPass : public ScriptPass { run("opt -fast -mux_undef -undriven -fine -full"); run("memory_map"); run("opt -undriven -fine"); - run("dff2dffe -direct-match $_DFF_*"); run("opt -fine"); run("techmap -map +/techmap.v"); run("opt -full"); run("clean -purge"); run("setundef -undriven -zero"); + run("dfflegalize -cell $_DFF_P_ x"); if (retime || help_mode) run("abc -markgroups -dff -D 1", "(only if -retime)"); } diff --git a/techlibs/intel/Makefile.inc b/techlibs/intel/Makefile.inc index f751e341f..fef6aab77 100644 --- a/techlibs/intel/Makefile.inc +++ b/techlibs/intel/Makefile.inc @@ -5,6 +5,7 @@ $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/m9k_bb.v)) $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/altpll_bb.v)) $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_m9k.txt)) $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map_m9k.v)) +$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/ff_map.v)) # Add the cell models and mappings for the VQM backend families := max10 arria10gx cyclonev cyclone10lp cycloneiv cycloneive diff --git a/techlibs/intel/common/ff_map.v b/techlibs/intel/common/ff_map.v new file mode 100644 index 000000000..e3f92adbb --- /dev/null +++ b/techlibs/intel/common/ff_map.v @@ -0,0 +1,11 @@ +// Async Active Low Reset DFF +module \$_DFFE_PN0P_ (input D, C, R, E, output Q); + parameter _TECHMAP_WIREINIT_Q_ = 1'bx; + generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) begin + dffeas #(.is_wysiwyg("TRUE"), .power_up("high")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(E), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); + end else begin + dffeas #(.is_wysiwyg("TRUE"), .power_up("low")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(E), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); + end + endgenerate + wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule diff --git a/techlibs/intel/cyclone10lp/cells_map.v b/techlibs/intel/cyclone10lp/cells_map.v index 25d73711c..22907b144 100644 --- a/techlibs/intel/cyclone10lp/cells_map.v +++ b/techlibs/intel/cyclone10lp/cells_map.v @@ -19,41 +19,6 @@ // > c60k28 (Viacheslav, VT) [at] yandex [dot] com // > Intel FPGA technology mapping. User must first simulate the generated \ // > netlist before going to test it on board. -// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed. - -// Normal mode DFF negedge clk, negedge reset -module \$_DFF_N_ (input D, C, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule -// Normal mode DFF -module \$_DFF_P_ (input D, C, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule - -// Async Active Low Reset DFF -module \$_DFF_PN0_ (input D, C, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule -// Async Active High Reset DFF -module \$_DFF_PP0_ (input D, C, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - wire R_i = ~ R; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule - -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - wire E_i = ~ E; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0)); -endmodule // Input buffer map module \$__inpad (input I, output O); diff --git a/techlibs/intel/cycloneiv/cells_map.v b/techlibs/intel/cycloneiv/cells_map.v index 56d32e586..41afd94be 100644 --- a/techlibs/intel/cycloneiv/cells_map.v +++ b/techlibs/intel/cycloneiv/cells_map.v @@ -19,41 +19,6 @@ // > c60k28 (Viacheslav, VT) [at] yandex [dot] com // > Intel FPGA technology mapping. User must first simulate the generated \ // > netlist before going to test it on board. -// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed. - -// Normal mode DFF negedge clk, negedge reset -module \$_DFF_N_ (input D, C, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule -// Normal mode DFF -module \$_DFF_P_ (input D, C, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule - -// Async Active Low Reset DFF -module \$_DFF_PN0_ (input D, C, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule -// Async Active High Reset DFF -module \$_DFF_PP0_ (input D, C, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - wire R_i = ~ R; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule - -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - wire E_i = ~ E; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0)); -endmodule // Input buffer map module \$__inpad (input I, output O); diff --git a/techlibs/intel/cycloneive/cells_map.v b/techlibs/intel/cycloneive/cells_map.v index 43a1183de..6d7f36ec5 100644 --- a/techlibs/intel/cycloneive/cells_map.v +++ b/techlibs/intel/cycloneive/cells_map.v @@ -19,41 +19,6 @@ // > c60k28 (Viacheslav, VT) [at] yandex [dot] com // > Intel FPGA technology mapping. User must first simulate the generated \ // > netlist before going to test it on board. -// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed. - -// Normal mode DFF negedge clk, negedge reset -module \$_DFF_N_ (input D, C, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule -// Normal mode DFF -module \$_DFF_P_ (input D, C, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule - -// Async Active Low Reset DFF -module \$_DFF_PN0_ (input D, C, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule -// Async Active High Reset DFF -module \$_DFF_PP0_ (input D, C, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - wire R_i = ~ R; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule - -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - wire E_i = ~ E; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0)); -endmodule // Input buffer map module \$__inpad (input I, output O); diff --git a/techlibs/intel/cyclonev/cells_map.v b/techlibs/intel/cyclonev/cells_map.v index 8223df3c6..0041481ab 100644 --- a/techlibs/intel/cyclonev/cells_map.v +++ b/techlibs/intel/cyclonev/cells_map.v @@ -19,43 +19,6 @@ // > c60k28 (Viacheslav, VT) [at] yandex [dot] com // > Intel FPGA technology mapping. User must first simulate the generated \ // > netlist before going to test it on board. -// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed. -// 2) Cyclone V 7-input LUT function was wrong implemented. Removed abc option to map this function \ -// and added the explanation in this file instead. Such function needs to be implemented. - -// Normal mode DFF negedge clk, negedge reset -module \$_DFF_N_ (input D, C, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule -// Normal mode DFF -module \$_DFF_P_ (input D, C, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule - -// Async Active Low Reset DFF -module \$_DFF_PN0_ (input D, C, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule -// Async Active High Reset DFF -module \$_DFF_PP0_ (input D, C, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - wire R_i = ~ R; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule - -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - wire E_i = ~ E; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0)); -endmodule // Input buffer map module \$__inpad (input I, output O); diff --git a/techlibs/intel/max10/cells_map.v b/techlibs/intel/max10/cells_map.v index 55b393080..8f198daef 100644 --- a/techlibs/intel/max10/cells_map.v +++ b/techlibs/intel/max10/cells_map.v @@ -19,41 +19,6 @@ // > c60k28 (Viacheslav, VT) [at] yandex [dot] com // > Intel FPGA technology mapping. User must first simulate the generated \ // > netlist before going to test it on board. -// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed. - -// Normal mode DFF negedge clk, negedge reset -module \$_DFF_N_ (input D, C, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule -// Normal mode DFF -module \$_DFF_P_ (input D, C, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule - -// Async Active Low Reset DFF -module \$_DFF_PN0_ (input D, C, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule -// Async Active High Reset DFF -module \$_DFF_PP0_ (input D, C, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - wire R_i = ~ R; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); -endmodule - -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); - parameter WYSIWYG="TRUE"; - parameter power_up=1'bx; - wire E_i = ~ E; - dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0)); -endmodule // Input buffer map module \$__inpad (input I, output O); diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index f3709498c..1fa98d098 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -212,6 +212,11 @@ struct SynthIntelPass : public ScriptPass { run("abc -markgroups -dff -D 1", "(only if -retime)"); } + if (check_label("map_ffs")) { + run("dfflegalize -cell $_DFFE_PN0P_ 01"); + run("techmap -map +/intel/common/ff_map.v"); + } + if (check_label("map_luts")) { if (family_opt == "arria10gx" || family_opt == "cyclonev") run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : "")); @@ -224,7 +229,6 @@ struct SynthIntelPass : public ScriptPass { if (iopads || help_mode) run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(if -iopads)"); run(stringf("techmap -map +/intel/%s/cells_map.v", family_opt.c_str())); - run("dffinit -highlow -ff dffeas q power_up"); run("clean -purge"); } diff --git a/techlibs/intel_alm/Makefile.inc b/techlibs/intel_alm/Makefile.inc index e36c81c0e..552f00c65 100644 --- a/techlibs/intel_alm/Makefile.inc +++ b/techlibs/intel_alm/Makefile.inc @@ -15,9 +15,9 @@ $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/ds $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/mem_sim.v)) # RAM -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_m10k.txt)) -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_m20k.txt)) -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_m20k_map.v)) +bramtypes := m10k m20k +$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype).txt))) +$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype)_map.v))) $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab.txt)) # Miscellaneous diff --git a/techlibs/intel_alm/common/bram_m10k.txt b/techlibs/intel_alm/common/bram_m10k.txt index e9355fe2c..837e3a330 100644 --- a/techlibs/intel_alm/common/bram_m10k.txt +++ b/techlibs/intel_alm/common/bram_m10k.txt @@ -1,4 +1,4 @@ -bram MISTRAL_M10K +bram __MISTRAL_M10K_SDP init 0 # TODO: Re-enable when I figure out how BRAM init works abits 13 @D8192x1 dbits 1 @D8192x1 @@ -27,7 +27,7 @@ bram MISTRAL_M10K endbram -match MISTRAL_M10K +match __MISTRAL_M10K_SDP min efficiency 5 make_transp endmatch diff --git a/techlibs/intel_alm/common/bram_m10k_map.v b/techlibs/intel_alm/common/bram_m10k_map.v new file mode 100644 index 000000000..061463c3e --- /dev/null +++ b/techlibs/intel_alm/common/bram_m10k_map.v @@ -0,0 +1,31 @@ +module __MISTRAL_M10K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+parameter CFG_ABITS = 10;
+parameter CFG_DBITS = 10;
+parameter CFG_ENABLE_A = 1;
+parameter CFG_ENABLE_B = 1;
+
+input CLK1;
+input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
+input [CFG_DBITS-1:0] A1DATA;
+output [CFG_DBITS-1:0] B1DATA;
+input [CFG_ENABLE_A-1:0] A1EN, B1EN;
+
+altsyncram #(
+ .operation_mode("dual_port"),
+ .ram_block_type("m10k"),
+ .widthad_a(CFG_ABITS),
+ .width_a(CFG_DBITS),
+ .widthad_b(CFG_ABITS),
+ .width_b(CFG_DBITS),
+) _TECHMAP_REPLACE_ (
+ .address_a(A1ADDR),
+ .data_a(A1DATA),
+ .wren_a(A1EN),
+ .address_b(B1ADDR),
+ .q_b(B1DATA),
+ .clock0(CLK1),
+ .clock1(CLK1)
+);
+
+endmodule
diff --git a/techlibs/intel_alm/common/megafunction_bb.v b/techlibs/intel_alm/common/megafunction_bb.v index 820b0430e..b5a3d8892 100644 --- a/techlibs/intel_alm/common/megafunction_bb.v +++ b/techlibs/intel_alm/common/megafunction_bb.v @@ -156,39 +156,4 @@ input [ax_width-1:0] ax; input [ay_scan_in_width-1:0] ay; output [result_a_width-1:0] resulta; -endmodule - -(* blackbox *) -module cyclonev_ram_block(portaaddr, portadatain, portawe, portbaddr, portbdataout, portbre, clk0); - -parameter operation_mode = "dual_port"; -parameter logical_ram_name = ""; -parameter port_a_address_width = 10; -parameter port_a_data_width = 10; -parameter port_a_logical_ram_depth = 1024; -parameter port_a_logical_ram_width = 10; -parameter port_a_first_address = 0; -parameter port_a_last_address = 1023; -parameter port_a_first_bit_number = 0; -parameter port_b_address_width = 10; -parameter port_b_data_width = 10; -parameter port_b_logical_ram_depth = 1024; -parameter port_b_logical_ram_width = 10; -parameter port_b_first_address = 0; -parameter port_b_last_address = 1023; -parameter port_b_first_bit_number = 0; -parameter port_b_address_clock = "clock0"; -parameter port_b_read_enable_clock = "clock0"; -parameter mem_init0 = ""; -parameter mem_init1 = ""; -parameter mem_init2 = ""; -parameter mem_init3 = ""; -parameter mem_init4 = ""; - -input [port_a_address_width-1:0] portaaddr; -input [port_b_address_width-1:0] portbaddr; -input [port_a_data_width-1:0] portadatain; -output [port_b_data_width-1:0] portbdataout; -input clk0, portawe, portbre; - -endmodule +endmodule
\ No newline at end of file diff --git a/techlibs/intel_alm/common/mem_sim.v b/techlibs/intel_alm/common/mem_sim.v index 23ffc6c87..f6f9ecb02 100644 --- a/techlibs/intel_alm/common/mem_sim.v +++ b/techlibs/intel_alm/common/mem_sim.v @@ -68,37 +68,3 @@ always @(posedge CLK1) assign B1DATA = mem[B1ADDR]; endmodule - -// The M10K -// -------- -// TODO - -module MISTRAL_M10K(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); - -parameter CFG_ABITS = 10; -parameter CFG_DBITS = 10; - -input CLK1; -input [CFG_ABITS-1:0] A1ADDR, B1ADDR; -input [CFG_DBITS-1:0] A1DATA; -input A1EN, B1EN; -output reg [CFG_DBITS-1:0] B1DATA; - -reg [2**CFG_ABITS * CFG_DBITS - 1 : 0] mem = 0; - -specify - $setup(A1ADDR, posedge CLK1, 0); - $setup(A1DATA, posedge CLK1, 0); - - if (B1EN) (posedge CLK1 => (B1DATA : A1DATA)) = 0; -endspecify - -always @(posedge CLK1) begin - if (A1EN) - mem[(A1ADDR + 1) * CFG_DBITS - 1 : A1ADDR * CFG_DBITS] <= A1DATA; - - if (B1EN) - B1DATA <= mem[(B1ADDR + 1) * CFG_DBITS - 1 : B1ADDR * CFG_DBITS]; -end - -endmodule diff --git a/techlibs/intel_alm/common/quartus_rename.v b/techlibs/intel_alm/common/quartus_rename.v index 926d2d64f..46ef2aa0d 100644 --- a/techlibs/intel_alm/common/quartus_rename.v +++ b/techlibs/intel_alm/common/quartus_rename.v @@ -123,51 +123,6 @@ module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1 endmodule -module MISTRAL_M10K(A1ADDR, A1DATA, A1EN, CLK1, B1ADDR, B1DATA, B1EN); - -parameter CFG_ABITS = 10; -parameter CFG_DBITS = 10; - -input [CFG_ABITS-1:0] A1ADDR, B1ADDR; -input [CFG_DBITS-1:0] A1DATA; -input CLK1, A1EN, B1EN; -output [CFG_DBITS-1:0] B1DATA; - -// Much like the MLAB, the M10K has mem_init[01234] parameters which would let -// you initialise the RAM cell via hex literals. If they were implemented. - -cyclonev_ram_block #( - .operation_mode("dual_port"), - .logical_ram_name("MISTRAL_M10K"), - .port_a_address_width(CFG_ABITS), - .port_a_data_width(CFG_DBITS), - .port_a_logical_ram_depth(2**CFG_ABITS), - .port_a_logical_ram_width(CFG_DBITS), - .port_a_first_address(0), - .port_a_last_address(2**CFG_DBITS - 1), - .port_a_first_bit_number(0), - .port_b_address_width(CFG_ABITS), - .port_b_data_width(CFG_DBITS), - .port_b_logical_ram_depth(2**CFG_ABITS), - .port_b_logical_ram_width(CFG_DBITS), - .port_b_first_address(0), - .port_b_last_address(2**CFG_DBITS - 1), - .port_b_first_bit_number(0), - .port_b_address_clock("clock0"), - .port_b_read_enable_clock("clock0") -) _TECHMAP_REPLACE_ ( - .portaaddr(A1ADDR), - .portadatain(A1DATA), - .portawe(A1EN), - .portbaddr(B1ADDR), - .portbdataout(B1DATA), - .portbre(B1EN), - .clk0(CLK1) -); - -endmodule - - module MISTRAL_MUL27X27(input [26:0] A, B, output [53:0] Y); `MAC #(.ax_width(27), .ay_scan_in_width(27), .result_a_width(54), .operation_mode("M27x27")) _TECHMAP_REPLACE_ (.ax(A), .ay(B), .resulta(Y)); diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc index 12137cdea..b751e8413 100644 --- a/techlibs/intel_alm/synth_intel_alm.cc +++ b/techlibs/intel_alm/synth_intel_alm.cc @@ -235,8 +235,7 @@ struct SynthIntelALMPass : public ScriptPass { if (!nobram && check_label("map_bram", "(skip if -nobram)")) { run(stringf("memory_bram -rules +/intel_alm/common/bram_%s.txt", bram_type.c_str())); - if (help_mode || bram_type != "m10k") - run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str())); + run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str())); } if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) { diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index de0de5974..421602e62 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -652,13 +652,13 @@ struct SynthXilinxPass : public ScriptPass } run("clean"); + if (help_mode || !abc9) + run("techmap -map +/xilinx/ff_map.v", "(only if not '-abc9')"); // This shregmap call infers fixed length shift registers after abc // has performed any necessary retiming if (!nosrl || help_mode) run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')"); std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v"; - if (help_mode || !abc9) - techmap_args += stringf(" -map +/xilinx/ff_map.v"); techmap_args += " -D LUT_WIDTH=" + lut_size_s; run("techmap " + techmap_args); if (help_mode) diff --git a/tests/arch/intel_alm/blockram.ys b/tests/arch/intel_alm/blockram.ys deleted file mode 100644 index 610ae1ffd..000000000 --- a/tests/arch/intel_alm/blockram.ys +++ /dev/null @@ -1,6 +0,0 @@ -read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 10 sync_ram_sdp -synth_intel_alm -family cyclonev -cd sync_ram_sdp -select -assert-count 1 t:MISTRAL_M10K -select -assert-none t:MISTRAL_M10K %% t:* %D diff --git a/tests/arch/xilinx/nosrl.ys b/tests/arch/xilinx/nosrl.ys new file mode 100644 index 000000000..31bd5d377 --- /dev/null +++ b/tests/arch/xilinx/nosrl.ys @@ -0,0 +1,41 @@ +read_verilog <<EOT + +module xilinx_srl_static_test(input i, clk, output [1:0] q); +reg head = 1'b0; +reg [3:0] shift1 = 4'b0000; +reg [3:0] shift2 = 4'b0000; + +always @(posedge clk) begin + head <= i; + shift1 <= {shift1[2:0], head}; + shift2 <= {shift2[2:0], head}; +end + +assign q = {shift2[3], shift1[3]}; +endmodule + +EOT + +design -save read + +hierarchy -top xilinx_srl_static_test +proc +#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +equiv_opt -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd xilinx_srl_static_test # Constrain all select calls below inside the top module +stat +select -assert-count 1 t:BUFG +select -assert-count 1 t:SRL16E +select -assert-none t:BUFG t:SRL16E %% t:* %D + +design -load read +hierarchy -top xilinx_srl_static_test +proc +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -nosrl -noiopad # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd xilinx_srl_static_test # Constrain all select calls below inside the top module +stat +select -assert-count 1 t:BUFG +select -assert-count 5 t:FDRE +select -assert-none t:BUFG t:FDRE %% t:* %D |