2018-07-13 07:52:25 -05:00
/*
* yosys - - Yosys Open SYnthesis Suite
*
* Copyright ( C ) 2012 Clifford Wolf < clifford @ clifford . at >
2019-07-09 16:26:10 -05:00
* Copyright ( C ) 2018 David Shah < dave @ ds0 . me >
2018-07-13 07:52:25 -05:00
*
* 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/register.h"
# include "kernel/celltypes.h"
# include "kernel/rtlil.h"
# include "kernel/log.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct SynthEcp5Pass : public ScriptPass
{
SynthEcp5Pass ( ) : ScriptPass ( " synth_ecp5 " , " synthesis for ECP5 FPGAs " ) { }
2020-06-18 18:34:52 -05:00
void on_register ( ) override
2020-05-04 13:44:00 -05:00
{
RTLIL : : constpad [ " synth_ecp5.abc9.W " ] = " 300 " ;
}
2020-06-18 18:34:52 -05:00
void help ( ) override
2018-07-13 07:52:25 -05:00
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log ( " \n " ) ;
log ( " synth_ecp5 [options] \n " ) ;
log ( " \n " ) ;
log ( " This command runs synthesis for ECP5 FPGAs. \n " ) ;
log ( " \n " ) ;
log ( " -top <module> \n " ) ;
log ( " use the specified module as top module \n " ) ;
log ( " \n " ) ;
log ( " -blif <file> \n " ) ;
log ( " write the design to the specified BLIF file. writing of an output file \n " ) ;
log ( " is omitted if this parameter is not specified. \n " ) ;
log ( " \n " ) ;
log ( " -edif <file> \n " ) ;
log ( " write the design to the specified EDIF file. writing of an output file \n " ) ;
log ( " is omitted if this parameter is not specified. \n " ) ;
log ( " \n " ) ;
log ( " -json <file> \n " ) ;
log ( " write the design to the specified JSON file. writing of an output file \n " ) ;
log ( " is omitted if this parameter is not specified. \n " ) ;
log ( " \n " ) ;
log ( " -run <from_label>:<to_label> \n " ) ;
log ( " only run the commands between the labels (see below). an empty \n " ) ;
log ( " from label is synonymous to 'begin', and empty to label is \n " ) ;
log ( " synonymous to the end of the command list. \n " ) ;
log ( " \n " ) ;
log ( " -noflatten \n " ) ;
log ( " do not flatten design before synthesis \n " ) ;
log ( " \n " ) ;
2020-04-14 09:51:23 -05:00
log ( " -dff \n " ) ;
log ( " run 'abc'/'abc9' with -dff option \n " ) ;
log ( " \n " ) ;
2018-07-13 07:52:25 -05:00
log ( " -retime \n " ) ;
2019-12-30 14:11:45 -06:00
log ( " run 'abc' with '-dff -D 1' options \n " ) ;
2018-07-13 07:52:25 -05:00
log ( " \n " ) ;
log ( " -noccu2 \n " ) ;
log ( " do not use CCU2 cells in output netlist \n " ) ;
log ( " \n " ) ;
log ( " -nodffe \n " ) ;
log ( " do not use flipflops with CE in output netlist \n " ) ;
log ( " \n " ) ;
log ( " -nobram \n " ) ;
2019-07-16 15:44:55 -05:00
log ( " do not use block RAM cells in output netlist \n " ) ;
2018-07-13 07:52:25 -05:00
log ( " \n " ) ;
2019-07-16 15:44:55 -05:00
log ( " -nolutram \n " ) ;
log ( " do not use LUT RAM cells in output netlist \n " ) ;
2018-07-13 07:52:25 -05:00
log ( " \n " ) ;
2019-06-26 11:33:48 -05:00
log ( " -nowidelut \n " ) ;
2018-07-13 07:52:25 -05:00
log ( " do not use PFU muxes to implement LUTs larger than LUT4s \n " ) ;
log ( " \n " ) ;
2019-12-07 07:04:36 -06:00
log ( " -asyncprld \n " ) ;
log ( " use async PRLD mode to implement DLATCH and DFFSR (EXPERIMENTAL) \n " ) ;
log ( " \n " ) ;
2018-07-13 07:52:25 -05:00
log ( " -abc2 \n " ) ;
log ( " run two passes of 'abc' for slightly improved logic density \n " ) ;
log ( " \n " ) ;
2019-06-14 06:02:12 -05:00
log ( " -abc9 \n " ) ;
log ( " use new ABC9 flow (EXPERIMENTAL) \n " ) ;
log ( " \n " ) ;
2018-07-13 07:52:25 -05:00
log ( " -vpr \n " ) ;
log ( " generate an output netlist (and BLIF file) suitable for VPR \n " ) ;
log ( " (this feature is experimental and incomplete) \n " ) ;
log ( " \n " ) ;
2019-08-08 09:18:59 -05:00
log ( " -nodsp \n " ) ;
log ( " do not map multipliers to MULT18X18D \n " ) ;
2019-07-08 09:40:12 -05:00
log ( " \n " ) ;
2018-07-13 07:52:25 -05:00
log ( " \n " ) ;
log ( " The following commands are executed by this synthesis command: \n " ) ;
help_script ( ) ;
log ( " \n " ) ;
}
string top_opt , blif_file , edif_file , json_file ;
2020-04-14 09:51:23 -05:00
bool noccu2 , nodffe , nobram , nolutram , nowidelut , asyncprld , flatten , dff , retime , abc2 , abc9 , nodsp , vpr ;
2018-07-13 07:52:25 -05:00
2020-06-18 18:34:52 -05:00
void clear_flags ( ) override
2018-07-13 07:52:25 -05:00
{
top_opt = " -auto-top " ;
blif_file = " " ;
edif_file = " " ;
json_file = " " ;
noccu2 = false ;
nodffe = false ;
nobram = false ;
2019-07-16 15:44:55 -05:00
nolutram = false ;
2019-06-26 11:33:48 -05:00
nowidelut = false ;
2019-12-07 07:04:36 -06:00
asyncprld = false ;
2018-07-13 07:52:25 -05:00
flatten = true ;
2020-04-14 09:51:23 -05:00
dff = false ;
2018-07-13 07:52:25 -05:00
retime = false ;
abc2 = false ;
vpr = false ;
2019-06-14 06:02:12 -05:00
abc9 = false ;
2019-08-08 09:18:59 -05:00
nodsp = false ;
2018-07-13 07:52:25 -05:00
}
2020-06-18 18:34:52 -05:00
void execute ( std : : vector < std : : string > args , RTLIL : : Design * design ) override
2018-07-13 07:52:25 -05:00
{
string run_from , run_to ;
clear_flags ( ) ;
size_t argidx ;
for ( argidx = 1 ; argidx < args . size ( ) ; argidx + + )
{
if ( args [ argidx ] = = " -top " & & argidx + 1 < args . size ( ) ) {
top_opt = " -top " + args [ + + argidx ] ;
continue ;
}
if ( args [ argidx ] = = " -blif " & & argidx + 1 < args . size ( ) ) {
blif_file = args [ + + argidx ] ;
continue ;
}
if ( args [ argidx ] = = " -edif " & & argidx + 1 < args . size ( ) ) {
edif_file = args [ + + argidx ] ;
continue ;
}
if ( args [ argidx ] = = " -json " & & argidx + 1 < args . size ( ) ) {
json_file = args [ + + argidx ] ;
continue ;
}
if ( args [ argidx ] = = " -run " & & argidx + 1 < args . size ( ) ) {
size_t pos = args [ argidx + 1 ] . find ( ' : ' ) ;
if ( pos = = std : : string : : npos )
break ;
run_from = args [ + + argidx ] . substr ( 0 , pos ) ;
run_to = args [ argidx ] . substr ( pos + 1 ) ;
continue ;
}
if ( args [ argidx ] = = " -flatten " ) {
flatten = true ;
continue ;
}
if ( args [ argidx ] = = " -noflatten " ) {
flatten = false ;
continue ;
}
2020-04-14 09:51:23 -05:00
if ( args [ argidx ] = = " -dff " ) {
dff = true ;
continue ;
}
2018-07-13 07:52:25 -05:00
if ( args [ argidx ] = = " -retime " ) {
retime = true ;
continue ;
}
if ( args [ argidx ] = = " -noccu2 " ) {
noccu2 = true ;
continue ;
}
if ( args [ argidx ] = = " -nodffe " ) {
nodffe = true ;
continue ;
}
if ( args [ argidx ] = = " -nobram " ) {
nobram = true ;
continue ;
}
2019-12-07 07:04:36 -06:00
if ( args [ argidx ] = = " -asyncprld " ) {
asyncprld = true ;
continue ;
}
2019-07-16 15:44:55 -05:00
if ( args [ argidx ] = = " -nolutram " | | /*deprecated alias*/ args [ argidx ] = = " -nodram " ) {
nolutram = true ;
2018-07-13 07:52:25 -05:00
continue ;
}
2019-07-16 15:44:55 -05:00
if ( args [ argidx ] = = " -nowidelut " | | /*deprecated alias*/ args [ argidx ] = = " -nomux " ) {
2019-06-26 11:33:48 -05:00
nowidelut = true ;
2018-07-16 07:33:13 -05:00
continue ;
}
2018-07-13 07:52:25 -05:00
if ( args [ argidx ] = = " -abc2 " ) {
abc2 = true ;
continue ;
}
if ( args [ argidx ] = = " -vpr " ) {
vpr = true ;
continue ;
}
2019-06-14 06:02:12 -05:00
if ( args [ argidx ] = = " -abc9 " ) {
abc9 = true ;
continue ;
}
2019-08-08 09:18:59 -05:00
if ( args [ argidx ] = = " -nodsp " ) {
nodsp = true ;
2019-07-08 09:40:12 -05:00
continue ;
}
2018-07-13 07:52:25 -05:00
break ;
}
extra_args ( args , argidx , design ) ;
if ( ! design - > full_selection ( ) )
2018-12-07 13:14:07 -06:00
log_cmd_error ( " This command only operates on fully selected designs! \n " ) ;
2018-07-13 07:52:25 -05:00
2019-07-10 14:47:48 -05:00
if ( abc9 & & retime )
log_cmd_error ( " -retime option not currently compatible with -abc9! \n " ) ;
2018-07-13 07:52:25 -05:00
log_header ( design , " Executing SYNTH_ECP5 pass. \n " ) ;
log_push ( ) ;
run_script ( design , run_from , run_to ) ;
log_pop ( ) ;
}
2020-06-18 18:34:52 -05:00
void script ( ) override
2018-07-13 07:52:25 -05:00
{
if ( check_label ( " begin " ) )
{
2020-02-12 13:30:37 -06:00
run ( " read_verilog -lib -specify +/ecp5/cells_sim.v +/ecp5/cells_bb.v " ) ;
2018-07-13 07:52:25 -05:00
run ( stringf ( " hierarchy -check %s " , help_mode ? " -top <top> " : top_opt . c_str ( ) ) ) ;
}
2019-09-26 12:45:14 -05:00
if ( check_label ( " coarse " ) )
2018-07-13 07:52:25 -05:00
{
run ( " proc " ) ;
2019-09-26 12:45:14 -05:00
if ( flatten | | help_mode )
run ( " flatten " ) ;
2018-07-13 07:52:25 -05:00
run ( " tribuf -logic " ) ;
run ( " deminout " ) ;
2019-07-08 09:40:12 -05:00
run ( " opt_expr " ) ;
run ( " opt_clean " ) ;
run ( " check " ) ;
run ( " opt " ) ;
run ( " wreduce " ) ;
run ( " peepopt " ) ;
run ( " opt_clean " ) ;
run ( " share " ) ;
run ( " techmap -map +/cmp2lut.v -D LUT_WIDTH=4 " ) ;
run ( " opt_expr " ) ;
run ( " opt_clean " ) ;
2019-08-08 09:18:59 -05:00
if ( ! nodsp ) {
2019-09-26 12:45:14 -05:00
run ( " techmap -map +/mul2dsp.v -map +/ecp5/dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18 " , " (unless -nodsp) " ) ;
2019-08-08 09:18:59 -05:00
run ( " chtype -set $mul t:$__soft_mul " , " (unless -nodsp) " ) ;
2019-07-08 09:40:12 -05:00
}
run ( " alumacc " ) ;
run ( " opt " ) ;
run ( " fsm " ) ;
run ( " opt -fast " ) ;
run ( " memory -nomap " ) ;
run ( " opt_clean " ) ;
2018-07-13 07:52:25 -05:00
}
2019-07-11 05:56:59 -05:00
if ( ! nobram & & check_label ( " map_bram " , " (skip if -nobram) " ) )
2018-07-13 07:52:25 -05:00
{
Harmonize BRAM/LUTRAM descriptions across all of Yosys.
This commit:
* renames all remaining instances of "DRAM" (which is ambiguous)
to "LUTRAM" (which is not), finishing the work started in
the commit 698ab9be;
* renames memory rule files to brams.txt/lutrams.txt;
* adds/renames script labels map_bram/map_lutram;
* extracts where necessary script labels map_ffram and map_gates;
* adds where necessary options -nobram/-nolutram.
The end result is that BRAM/LUTRAM/FFRAM aspects of every target
are now consistent with each other.
Per architecture:
* anlogic: rename drams.txt→lutrams.txt, add -nolutram, add
:map_lutram, :map_ffram, :map_gates
* ecp5: rename bram.txt→brams.txt, lutram.txt→lutrams.txt
* efinix: rename bram.txt→brams.txt, add -nobram, add :map_ffram,
:map_gates
* gowin: rename bram.txt→brams.txt, dram.txt→lutrams.txt,
rename -nodram→-nolutram (-nodram still recognized), rename
:bram→:map_bram, :dram→:map_lutram, add :map_ffram, :map_gates
2020-01-01 06:30:00 -06:00
run ( " memory_bram -rules +/ecp5/brams.txt " ) ;
2018-07-13 07:52:25 -05:00
run ( " techmap -map +/ecp5/brams_map.v " ) ;
}
2019-07-16 15:44:55 -05:00
if ( ! nolutram & & check_label ( " map_lutram " , " (skip if -nolutram) " ) )
2018-07-13 07:52:25 -05:00
{
Harmonize BRAM/LUTRAM descriptions across all of Yosys.
This commit:
* renames all remaining instances of "DRAM" (which is ambiguous)
to "LUTRAM" (which is not), finishing the work started in
the commit 698ab9be;
* renames memory rule files to brams.txt/lutrams.txt;
* adds/renames script labels map_bram/map_lutram;
* extracts where necessary script labels map_ffram and map_gates;
* adds where necessary options -nobram/-nolutram.
The end result is that BRAM/LUTRAM/FFRAM aspects of every target
are now consistent with each other.
Per architecture:
* anlogic: rename drams.txt→lutrams.txt, add -nolutram, add
:map_lutram, :map_ffram, :map_gates
* ecp5: rename bram.txt→brams.txt, lutram.txt→lutrams.txt
* efinix: rename bram.txt→brams.txt, add -nobram, add :map_ffram,
:map_gates
* gowin: rename bram.txt→brams.txt, dram.txt→lutrams.txt,
rename -nodram→-nolutram (-nodram still recognized), rename
:bram→:map_bram, :dram→:map_lutram, add :map_ffram, :map_gates
2020-01-01 06:30:00 -06:00
run ( " memory_bram -rules +/ecp5/lutrams.txt " ) ;
2019-07-16 15:44:55 -05:00
run ( " techmap -map +/ecp5/lutrams_map.v " ) ;
2018-07-13 07:52:25 -05:00
}
2019-07-11 05:56:59 -05:00
if ( check_label ( " map_ffram " ) )
2018-07-13 07:52:25 -05:00
{
run ( " opt -fast -mux_undef -undriven -fine " ) ;
2020-01-01 04:11:35 -06:00
run ( " memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
" -attr syn_ramstyle=auto -attr syn_ramstyle=registers "
" -attr syn_romstyle=auto -attr syn_romstyle=logic " ) ;
2018-07-13 07:52:25 -05:00
run ( " opt -undriven -fine " ) ;
2019-07-11 05:56:59 -05:00
}
if ( check_label ( " map_gates " ) )
{
2018-07-13 08:46:12 -05:00
if ( noccu2 )
2018-07-13 07:52:25 -05:00
run ( " techmap " ) ;
else
run ( " techmap -map +/techmap.v -map +/ecp5/arith_map.v " ) ;
2020-02-05 20:39:01 -06:00
run ( " opt -fast " ) ;
2018-07-13 07:52:25 -05:00
if ( retime | | help_mode )
2019-12-30 14:09:53 -06:00
run ( " abc -dff -D 1 " , " (only if -retime) " ) ;
2018-07-13 07:52:25 -05:00
}
if ( check_label ( " map_ffs " ) )
{
2020-04-14 14:56:28 -05:00
run ( " dff2dffs " ) ;
2018-07-14 08:54:30 -05:00
run ( " opt_clean " ) ;
2018-07-13 07:52:25 -05:00
if ( ! nodffe )
2020-06-23 10:25:46 -05:00
run ( " dff2dffe -direct-match $_DFF_* -direct-match $_SDFF_* " ) ;
2020-07-02 17:23:03 -05:00
if ( help_mode )
run ( " dfflegalize -cell $_DFF_?_ 01 -cell $_DFFE_??_ 01 -cell $_DFF_?P?_ r -cell $_DFFE_?P??_ r -cell $_SDFF_?P?_ r -cell $_SDFFE_?P??_ r -cell $_DLATCH_?_ x [-cell $_DFFSR_?PP_ x] " , " ($_DFFSR_*_ only if -asyncprld) " ) ;
else if ( asyncprld )
run ( " dfflegalize -cell $_DFF_?_ 01 -cell $_DFFE_??_ 01 -cell $_DFF_?P?_ r -cell $_DFFE_?P??_ r -cell $_SDFF_?P?_ r -cell $_SDFFE_?P??_ r -cell $_DLATCH_?_ x -cell $_DFFSR_?PP_ x " ) ;
else
run ( " dfflegalize -cell $_DFF_?_ 01 -cell $_DFFE_??_ 01 -cell $_DFF_?P?_ r -cell $_DFFE_?P??_ r -cell $_SDFF_?P?_ r -cell $_SDFFE_?P??_ r -cell $_DLATCH_?_ x " ) ;
2020-04-14 09:51:23 -05:00
if ( ( abc9 & & dff ) | | help_mode )
2020-06-23 10:25:46 -05:00
run ( " zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF* " , " (only if -abc9 and -dff " ) ;
2019-12-07 07:04:36 -06:00
run ( stringf ( " techmap -D NO_LUT %s -map +/ecp5/cells_map.v " , help_mode ? " [-D ASYNC_PRLD] " : ( asyncprld ? " -D ASYNC_PRLD " : " " ) ) ) ;
2019-04-30 07:46:12 -05:00
run ( " opt_expr -undriven -mux_undef " ) ;
2018-07-13 07:52:25 -05:00
run ( " simplemap " ) ;
2019-08-27 07:07:06 -05:00
run ( " ecp5_gsr " ) ;
2019-10-10 09:58:31 -05:00
run ( " attrmvcp -copy -attr syn_useioff " ) ;
2019-08-27 07:07:06 -05:00
run ( " opt_clean " ) ;
2018-07-13 07:52:25 -05:00
}
if ( check_label ( " map_luts " ) )
{
2020-05-13 16:16:42 -05:00
if ( abc2 | | help_mode )
2018-07-13 07:52:25 -05:00
run ( " abc " , " (only if -abc2) " ) ;
2020-05-13 16:42:18 -05:00
if ( ! asyncprld | | help_mode )
run ( " techmap -map +/ecp5/latches_map.v " , " (skip if -asyncprld) " ) ;
2019-08-20 20:59:03 -05:00
2019-06-14 06:02:12 -05:00
if ( abc9 ) {
2020-05-04 13:44:00 -05:00
std : : string abc9_opts ;
if ( nowidelut )
abc9_opts + = " -maxlut 4 " ;
std : : string k = " synth_ecp5.abc9.W " ;
if ( active_design & & active_design - > scratchpad . count ( k ) )
abc9_opts + = stringf ( " -W %s " , active_design - > scratchpad_get_string ( k ) . c_str ( ) ) ;
else
abc9_opts + = stringf ( " -W %s " , RTLIL : : constpad . at ( k ) . c_str ( ) ) ;
2019-06-26 12:23:29 -05:00
if ( nowidelut )
2020-05-13 16:12:06 -05:00
abc9_opts + = " -maxlut 4 " ;
2020-04-14 09:51:23 -05:00
if ( dff )
2020-05-13 16:12:06 -05:00
abc9_opts + = " -dff " ;
run ( " abc9 " + abc9_opts ) ;
2019-06-14 06:02:12 -05:00
} else {
2020-04-14 09:51:23 -05:00
std : : string abc_args = " -dress " ;
2019-06-26 12:04:01 -05:00
if ( nowidelut )
2020-04-14 09:51:23 -05:00
abc_args + = " -lut 4 " ;
2019-06-14 06:02:12 -05:00
else
2020-04-14 09:51:23 -05:00
abc_args + = " -lut 4:7 " ;
if ( dff )
abc_args + = " -dff " ;
run ( " abc " + abc_args ) ;
2019-06-14 06:02:12 -05:00
}
2018-07-13 07:52:25 -05:00
run ( " clean " ) ;
}
if ( check_label ( " map_cells " ) )
{
2020-04-14 09:51:23 -05:00
if ( help_mode )
run ( " techmap -map +/ecp5/cells_map.v " , " (skip if -vpr) " ) ;
else if ( ! vpr )
run ( " techmap -map +/ecp5/cells_map.v " ) ;
2020-02-03 07:57:17 -06:00
run ( " opt_lut_ins -tech ecp5 " ) ;
2018-07-13 07:52:25 -05:00
run ( " clean " ) ;
}
if ( check_label ( " check " ) )
{
2019-11-15 15:03:11 -06:00
run ( " autoname " ) ;
2018-07-13 07:52:25 -05:00
run ( " hierarchy -check " ) ;
run ( " stat " ) ;
run ( " check -noinit " ) ;
}
if ( check_label ( " blif " ) )
{
if ( ! blif_file . empty ( ) | | help_mode ) {
if ( vpr | | help_mode ) {
run ( stringf ( " opt_clean -purge " ) ,
" (vpr mode) " ) ;
run ( stringf ( " write_blif -attr -cname -conn -param %s " ,
help_mode ? " <file-name> " : blif_file . c_str ( ) ) ,
" (vpr mode) " ) ;
}
if ( ! vpr )
run ( stringf ( " write_blif -gates -attr -param %s " ,
help_mode ? " <file-name> " : blif_file . c_str ( ) ) ,
" (non-vpr mode) " ) ;
}
}
if ( check_label ( " edif " ) )
{
if ( ! edif_file . empty ( ) | | help_mode )
run ( stringf ( " write_edif %s " , help_mode ? " <file-name> " : edif_file . c_str ( ) ) ) ;
}
if ( check_label ( " json " ) )
{
if ( ! json_file . empty ( ) | | help_mode )
run ( stringf ( " write_json %s " , help_mode ? " <file-name> " : json_file . c_str ( ) ) ) ;
}
}
} SynthEcp5Pass ;
PRIVATE_NAMESPACE_END