blob: ea438d95bad1436dfe2cc7c17db67a27eff5c82d [file] [log] [blame] [edit]
yosys -import
plugin -i ql-iob
plugin -i ql-qlf
yosys -import
# Read VPR cells library
read_verilog -lib -specify $::env(TECHMAP_PATH)/cells_sim.v
# Read device specific cells library
read_verilog -lib -specify $::env(DEVICE_CELLS_SIM)
# Synthesize
synth_quicklogic -family pp3
# Optimize the netlist by adaptively splitting cells that fit into C_FRAG into
# smaller that can fit into F_FRAG.
proc max {a b} {
if {$a > $b} {
return $a
} else {
return $b
}
}
proc min {a b} {
if {$a < $b} {
return $a
} else {
return $b
}
}
# Returns the required number of C_FRAGs to fit the design
proc get_used_c_frag {} {
set used_c_frag [get_count -cells t:mux8x0 t:LUT4 t:logic_cell_macro]
set used_t_frag [get_count -cells t:mux4x0 t:LUT2 t:LUT3]
set used_c_frag_for_t_frag [expr int(ceil($used_t_frag / 2.0))]
return [expr $used_c_frag + $used_c_frag_for_t_frag]
}
# Returns the required number of F_FRAGs to fit the design
proc get_used_f_frag {} {
return [get_count -cells t:inv t:mux2x0 t:LUT1 t:logic_cell_macro]
}
# Load the plugin that allows to retrieve cell count
yosys plugin -i design_introspection
yosys -import
# Maximum number of LOGIC cells in the device
set max_logic 891
# Target number of LOGIC cells. This is less than max to allow the VPR
# packet to have more freedom.
set target_logic [expr int($max_logic * 0.90)]
puts "PACK: Optimizing for target of $target_logic/$max_logic LOGIC cells"
# LUT3 -> mux2x0 (replace)
set used_c_frag [get_used_c_frag]
if {$used_c_frag > $target_logic} {
puts "PACK: Device overfitted $used_c_frag / $target_logic"
# Update
set required_frags [expr 2 * ($used_c_frag - $target_logic)]
set used_f_frag [get_used_f_frag]
set free_f_frag [expr $target_logic - $used_f_frag]
# Try converting LUT3 to mux2x0
if {$free_f_frag > 0} {
puts "PACK: Replacing at most $free_f_frag LUT3 with mux2x0"
set sel_count [min $required_frags $free_f_frag]
yosys techmap -map $::env(TECHMAP_PATH)/lut3tomux2.v t:LUT3 %R$sel_count
}
}
# LUT2 -> mux2x0 (replace)
set used_c_frag [get_used_c_frag]
if {$used_c_frag > $target_logic} {
puts "PACK: Device overfitted $used_c_frag / $target_logic"
# Update
set required_frags [expr 2 * ($used_c_frag - $target_logic)]
set used_f_frag [get_used_f_frag]
set free_f_frag [expr $target_logic - $used_f_frag]
# Try converting LUT2 to mux2x0
if {$free_f_frag > 0} {
puts "PACK: Replacing at most $free_f_frag LUT2 with mux2x0"
set sel_count [min $required_frags $free_f_frag]
yosys techmap -map $::env(TECHMAP_PATH)/lut2tomux2.v t:LUT2 %R$sel_count
}
}
# Split mux4x0
set used_c_frag [get_used_c_frag]
if {$used_c_frag > $target_logic} {
puts "PACK: Device overfitted $used_c_frag / $target_logic"
# Update
set required_frags [expr 2 * ($used_c_frag - $target_logic)]
set used_f_frag [get_used_f_frag]
set free_f_frag [expr $target_logic - $used_f_frag]
# Try converting mux4x0 to 3x mux2x0
if {$free_f_frag >= 3} {
puts "PACK: Splitting at most $free_f_frag mux4x0 to 3x mux2x0"
set sel_count [min $required_frags [expr int(floor($free_f_frag / 3.0))]]
# If there are not enough mux4x0 then map some LUT2 to them (these are
# actually equivalent)
set mux4_count [get_count -cells t:mux4x0]
if {$mux4_count < $sel_count} {
set map_count [expr $sel_count - $mux4_count]
puts "PACK: Replacing at most $map_count LUT2 with mux4x0"
yosys techmap -map $::env(TECHMAP_PATH)/lut2tomux4.v t:LUT2 %R$map_count
}
yosys techmap -map $::env(TECHMAP_PATH)/mux4tomux2.v t:mux4x0 %R$sel_count
}
}
# Split mux8x0
set used_c_frag [get_used_c_frag]
if {$used_c_frag > $target_logic} {
puts "PACK: Device overfitted $used_c_frag / $target_logic"
# Update
set required_frags [expr 2 * ($used_c_frag - $target_logic)]
set used_f_frag [get_used_f_frag]
set free_f_frag [expr $target_logic - $used_f_frag]
# Try converting mux8x0 to 7x mux2x0
if {$free_f_frag >= 7} {
puts "PACK: Splitting at most $free_f_frag mux8x0 to 7x mux2x0"
set sel_count [min $required_frags [expr int(floor($free_f_frag / 7.0))]]
yosys techmap -map $::env(TECHMAP_PATH)/mux8tomux2.v t:mux8x0 %R$sel_count
}
}
# Final check
set used_c_frag [get_used_c_frag]
if {$used_c_frag > $target_logic} {
puts "PACK: Device overfitted $used_c_frag / $target_logic. No more optimization possible!"
}
stat
# Assing parameters to IO cells basing on constraints and package pinmap
if { $::env(PCF_FILE) != "" && $::env(PINMAP_FILE) != ""} {
quicklogic_iob $::env(PCF_FILE) $::env(PINMAP_FILE)
}
# Write a pre-mapped design
write_verilog $::env(OUT_SYNTH_V).premap.v
# Select all logic_0 and logic_1 and apply the techmap to them first. This is
# necessary for constant connection detection in the subsequent techmaps.
select -set consts t:logic_0 t:logic_1
techmap -map $::env(TECHMAP_PATH)/cells_map.v @consts
# Map to the VPR cell library
techmap -map $::env(TECHMAP_PATH)/cells_map.v
# Map to the device specific VPR cell library
techmap -map $::env(DEVICE_CELLS_MAP)
# opt_expr -undriven makes sure all nets are driven, if only by the $undef
# net.
opt_expr -undriven
opt_clean
setundef -zero -params
stat
# Write output JSON, fixup cell names using an external Python script
write_json $::env(OUT_JSON).org.json
exec $::env(PYTHON3) -m f4pga.utils.quicklogic.yosys_fixup_cell_names $::env(OUT_JSON).org.json $::env(OUT_JSON)
# Read the fixed JSON back and write verilog
design -reset
read_json $::env(OUT_JSON)
write_verilog $::env(OUT_SYNTH_V)
design -reset
exec $::env(PYTHON3) -m f4pga.utils.yosys_split_inouts -i $::env(OUT_JSON) -o $::env(SYNTH_JSON)
read_json $::env(SYNTH_JSON)
yosys -import
opt_clean
write_blif -attr -cname -param \
-true VCC VCC \
-false GND GND \
-undef VCC VCC \
$::env(OUT_EBLIF)