[syn] Synth flow improvements

Adds significant functionality to synthesis flow. Timing reports are
generated using OpenSTA and an area report is generated. Flow supports
open Nangate45 library from OpenROAD.
This commit is contained in:
Greg Chadwick 2019-09-26 15:27:08 +01:00
parent 9c6ddae626
commit 79bb6c7832
22 changed files with 788 additions and 116 deletions

142
syn/README.md Normal file
View file

@ -0,0 +1,142 @@
**This synthesis flow is experimental and under development, it does not produce
tape-out quality netlists and area/timing numbers it generates are not
representative of what would be achievable with a tape-out quality flow**
# Yosys/OpenSTA Ibex Synthesis Flow
This is a synthesis-only implementation flow using Yosys for Synthesis and
OpenSTA to produce timing reports. Its outputs are:
* A pre-mapping netlist - Gate-level verilog using generic gates that hasn't
been mapped to a standard-cell library yet
* A post synthesis netlist - Gate-level verilog after optimisation mapped to a
standard-cell library
* An STA netlist - Logically equivilent to the netlist above but with changes to
allow processing by OpenSTA
* Area/Cell Usage report - Total area consumed by utilised cells and counts of
each cell instance used
* Timing reports - Overal timing report and reports broken down into various
path groups (register to register paths and per IO reports)
Yosys doesn't yet support the full subset of SystemVerilog used by Ibex so the
sv2v tool is used to first convert the Ibex RTL into the SystemVerilog subset
Yosys can process.
# Synthesis flow requirements
The following must be installed:
* Python 3 (version >= 3.5)
* sv2v - https://github.com/zachjs/sv2v
* Yosys - https://github.com/YosysHQ/yosys
* OpenSTA - https://github.com/The-OpenROAD-Project/OpenSTA
A standard cell library is also required in the liberty (.lib) format. The
following Open Libraries can be used:
* Nangate45 - https://github.com/The-OpenROAD-Project/OpenROAD-flow/tree/master/flow/platforms/nangate45
# Synthesis flow setup
The synthesis flow is configured via environment variables. The `syn_setup.sh`
file is used to set the environment variables for the flow and any changes made
should be placed there. An example `syn_setup.example.sh` is included. A copy
of this named `syn_setup.sh` must be made and the values in it set appropriately
for the flow to work.
The environment variables that must be set in `syn_setup.sh` are
* `LR_SYNTH_CELL_LIBRARY_PATH` - The path to the standard cell library, this
should point to the absolute path of the Nangate45 library
(`NangateOpenCellLibrary_typical.lib`).
* `LR_SYNTH_CELL_LIBRARY_NAME` - The name of the standard cell library, this is
used to alter the flow configuration for the library, currently 'nangate' is
the only supported value
# Running the synthesis flow
Once `syn_setup.sh` has been created the `syn_yosys.sh` will run the entire
flow. All outputs are placed in a directory with the prefix `syn_out_` with the
current date/time forming the rest of the name, e.g.
`syn_out_06_01_2020_11_19_15`
- `syn_out_dir`
- `reports` - All of the generated reports
- area.rpt - Total area used and per cell instance counts
- `timing`
- *.rpt - Raw reports from OpenSTA, gives full paths
- *.csv.rpt - CSV reports gives start and end point and slack
- `log`
- syn.log - Log of the Yosys run
- sta.log - Log of the OpenSTA run
- `generated`
- *.v - Ibex RTL after sv2v processing
- ibex_core.pre_map.v - Pre-mapping synthesis netlists
- ibex_core_netlist.v - Post-synthesis netlist
- ibex_core_netlist.sta.v - Post-synthesis netlist usable by OpenSTA
- ibex_core.[library-name].out.sdc - Generated .sdc timing constraints
file
# Timing constraints
Two files specify the timing constraints and timing related settings for the
flow. These are used to generate a single .sdc file
* `ibex_core_lr_synth_core.tcl` - This specifies the constraints on all inputs
and outputs as a fraction of a clock cycle, the names of the clock and reset
inputs and the desired clock period in ps
* `ibex.[library-name].sdc` - Header to include in generated .sdc file. Settings
can be library dependent so the `LR_SYNTH_CELL_LIBRARY_NAME` environment
varible is used to supply the `[library-name]` part of the name
# Timing reports
Timing reports are produced for the following path groups
* Overall - Every path in the design, WNS (worst negative slack) from this report is the design WNS
that limits the frequency
* reg2reg - Paths from register to register
* in2x - Paths from an input to any end point, one report is produced per named
input (e.g. `instr_data_i` has its own report)
* x2out - Paths from any start point to an output, one report is produced per
named output (e.g. `data_wdata_o` has its own report)
They are available in two formats .rpt and .csv.rpt. The .rpt is the full output
from OpenSTA and gives the full path between the start and end points. The CSV
version contains the start-point, end-point and WNS (one path per line). CSV
reports have had their start and end points translated to human readable names
(though this isn't 100% reliable). The raw OpenSTA reports generally contain
only generated cell names so will require further netlist inspection (via Yosys
or simply looking at the netlist .v) to make sense of.
# Post-synthesis inspection
Both Yosys and OpenSTA can be run to perform further inspection on the generated
synthesis. TCL is provided to setup the tools appropriately.
First the environment variables must be setup for the flow and the directory
containing the synthesis output set. This can be done with `syn_setup.sh`
```
$ source syn_setup.sh syn_out_06_01_2020_11_19_15/
```
Where `syn_out_06_01_2020_11_19_15/` is directory containing the synthesis
outputs. Then start Yosys or OpenSTA and run one of the provided TCL files
* `./tcl/yosys_pre_map.tcl` - Loads the pre-mapping netlist
* `./tcl/yosys_post_synth.tcl` - Load the post-synthesis netlist
So to load the post-synthesis netlist in Yosys:
```
$ yosys
yosys> tcl ./tcl/yosys_post_synth.tcl
```
To open the design in OpenSTA
```
$ sta
% source ./tcl/sta_open_design.tcl
```

View file

@ -1,73 +0,0 @@
// yosys -- Yosys Open SYnthesis Suite
//
// Copyright (C) 2012 - 2019 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.
// This file is copied from here:
// https://github.com/YosysHQ/yosys/blob/master/examples/cmos/cmos_cells.lib
/* test comment */
library(demo) {
cell(BUF) {
area: 6;
pin(A) { direction: input; }
pin(Y) { direction: output;
function: "A"; }
}
cell(NOT) {
area: 3;
pin(A) { direction: input; }
pin(Y) { direction: output;
function: "A'"; }
}
cell(NAND) {
area: 4;
pin(A) { direction: input; }
pin(B) { direction: input; }
pin(Y) { direction: output;
function: "(A*B)'"; }
}
cell(NOR) {
area: 4;
pin(A) { direction: input; }
pin(B) { direction: input; }
pin(Y) { direction: output;
function: "(A+B)'"; }
}
cell(DFF) {
area: 18;
ff(IQ, IQN) { clocked_on: C;
next_state: D; }
pin(C) { direction: input;
clock: true; }
pin(D) { direction: input; }
pin(Q) { direction: output;
function: "IQ"; }
}
cell(DFFSR) {
area: 18;
ff("IQ", "IQN") { clocked_on: C;
next_state: D;
preset: S;
clear: R; }
pin(C) { direction: input;
clock: true; }
pin(D) { direction: input; }
pin(Q) { direction: output;
function: "IQ"; }
pin(S) { direction: input; }
pin(R) { direction: input; }
; // empty statement
}
}

View file

@ -0,0 +1,6 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
set_driving_cell BUF_X2
set_load 10.0 [all_outputs]

View file

@ -0,0 +1,56 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
# List of inputs and outputs. Number is timing constraint expressed as a % of
# clock cycle, e.g.
#
# {instr_req_o 70.0}
#
# as an output means the instr_req_o output must be stable by 60% of total clock
# cycle
#
# {instr_gnt_i 30.0}
#
# as an input means the instr_gnt_i input will be stable by 30% of the total
# clock cycle
# These IO constraints are an educated guess, they effectively assume there's a
# bit of external logic on the inputs and outputs but not much before they reach
# a flop.
set lr_synth_outputs [list {instr_req_o 70.0} \
{instr_addr_o 70.0} \
{data_req_o 70.0} \
{data_we_o 70.0} \
{data_be_o 70.0} \
{data_addr_o 70.0} \
{data_wdata_o 70.0} \
{core_sleep_o 80.0}]
set lr_synth_inputs [list {test_en_i 0.0 } \
{hart_id_i 0.0 } \
{boot_addr_i 0.0 } \
{instr_gnt_i 30.0} \
{instr_rvalid_i 30.0} \
{instr_rdata_i 30.0} \
{instr_err_i 30.0} \
{data_gnt_i 30.0} \
{data_rvalid_i 30.0} \
{data_rdata_i 30.0} \
{data_err_i 30.0} \
{irq_software_i 10.0} \
{irq_timer_i 10.0} \
{irq_external_i 10.0} \
{irq_fast_i 10.0} \
{irq_nm_i 10.0} \
{debug_req_i 10.0} \
{fetch_enable_i 0.0 }]
# clock and reset IO names (at top-level)
set lr_synth_clk_input clk_i
set lr_synth_rst_input rst_ni
# clock period in ps, this gives a 250 MHz clock. using the nangate45 library
# Ibex can meet this on reg2reg paths but sees some failures on the IO paths
set lr_synth_clk_period 4000.0

View file

@ -0,0 +1,47 @@
#!/usr/bin/python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
import argparse
import subprocess
from flow_utils import *
def main():
arg_parser = argparse.ArgumentParser(
description=
"""Uses yosys to translate cell names from given timing reports to human
readable names (assumes flatted synthesis run)""")
arg_parser.add_argument('top_level', help='Name of the top-level module')
arg_parser.add_argument(
'gen_out', help='Path to place generated script and script output')
arg_parser.add_argument(
'rpts',
nargs='+',
help='Report files to generate human readable names from')
args = arg_parser.parse_args()
cells_to_translate = set()
for csv_rpt in args.rpts:
(new_cells_to_translate, path_info) = extract_path_info(csv_rpt)
cells_to_translate.update(new_cells_to_translate)
create_translate_names_script(cells_to_translate, args.top_level,
args.gen_out)
yosys_cmd = [
'yosys', '-s', '{}/{}'.format(args.gen_out,
ys_translate_script_filename)
]
subprocess.run(yosys_cmd)
if __name__ == "__main__":
main()

82
syn/python/flow_utils.py Normal file
View file

@ -0,0 +1,82 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
import csv
import os
import re
import sys
ys_translate_script_filename = 'translate_names.ys'
ys_translated_names = 'ys_translated_names'
generated_cell_re = re.compile(r'(_\w+_)/(\w+)')
ys_tcl = './tcl/yosys_post_synth.tcl'
def create_translate_names_script(cells_to_translate, top_level, gen_out):
yosys_script_file = open(
'{}/{}'.format(gen_out, ys_translate_script_filename), 'w')
yosys_script_file.write('tcl {}\n'.format(ys_tcl))
yosys_script_file.write('cd {}\n'.format(top_level))
for cell in cells_to_translate:
yosys_script_file.write('select {} %x:+[Q]\n'.format(cell))
yosys_script_file.write('tee -a {}/{} select -list\n'.format(
gen_out, ys_translated_names))
yosys_script_file.close()
def extract_path_info(timing_csv):
timing_in = csv.reader(open(timing_csv))
cells_to_translate = set()
path_info = []
for line in timing_in:
points = []
for i in range(2):
cell_match = generated_cell_re.search(line[i])
if cell_match:
cells_to_translate.add(cell_match.group(1))
points.append(cell_match.group(1))
else:
points.append(line[i])
path_info.append((points[0], points[1], float(line[2])))
return (cells_to_translate, path_info)
def build_translated_names_dict(translated_names_file):
translated_names = open(translated_names_file)
translated_name_lines = translated_names.readlines()
translated_names_dict = {}
for i in range(0, len(translated_name_lines), 2):
translated_name = translated_name_lines[i][:-1].split('/', 1)[1]
cell_name = translated_name_lines[i + 1][:-1].split('/', 1)[1]
translated_names_dict[cell_name] = translated_name
return translated_names_dict
def translate_path_info(path_info, translated_names_file):
translated_names_dict = build_translated_names_dict(translated_names_file)
new_path_info = []
for path in path_info:
translated_path = list(path)
points = path[0:1]
for i in range(2):
if path[i] in translated_names_dict:
translated_path[i] = translated_names_dict[path[i]]
new_path_info.append(tuple(translated_path))
return new_path_info

View file

@ -0,0 +1,41 @@
#!/usr/bin/python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
import argparse
from flow_utils import *
def main():
arg_parser = argparse.ArgumentParser(
description=
"""Translates CSV timing report to have human readable start and end
points given yosys generated name translation file (generated with
build_translated_names.py""")
arg_parser.add_argument('rpt_file', help='Name of the CSV report file')
arg_parser.add_argument(
'gen_out', help='Path containing generated name translation file')
args = arg_parser.parse_args()
(cells_to_translate, path_info) = extract_path_info(args.rpt_file)
path_info = translate_path_info(
path_info, '{}/{}'.format(args.gen_out, ys_translated_names))
translated_rpt_out = open(sys.argv[1], 'w')
translated_rpt_out.write('Start Point, End Point, WNS (ns)\n')
for p in path_info:
translated_rpt_out.write('{},{},{}\n'.format(p[0], p[1], p[2]))
translated_rpt_out.close()
if __name__ == "__main__":
main()

View file

@ -1,18 +0,0 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
# yosys synthesis script
read -sv prim_clock_gating.v syn_out/*.v
synth -top ibex_core
write_verilog ibex_core_premap.v
# mapping to cmos_cells.lib
dfflibmap -liberty cmos_cells.lib
abc -liberty cmos_cells.lib
write_verilog ibex_core_netlist.v
# reports
check
stat

23
syn/syn_setup.example.sh Normal file
View file

@ -0,0 +1,23 @@
#!/bin/bash
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
if [ $# -eq 1 ]; then
export LR_SYNTH_OUT_DIR=$1
elif [ $# -eq 0 ]; then
export LR_SYNTH_OUT_DIR_PREFIX=syn_out
export LR_SYNTH_OUT_DIR=$(date +"${LR_SYNTH_OUT_DIR_PREFIX}_%d_%m_%Y_%H_%M_%S")
else
echo "Usage $0 [synth_out_dir]"
exit 1
fi
export LR_SYNTH_TIMING_RUN=1
export LR_SYNTH_FLATTEN=1
# SETUP CELL LIBRARY PATH
# Uncomment the lines below and set the path to an appropriate .lib file
# export LR_SYNTH_CELL_LIBRARY_PATH=/path/to/NangateOpenCellLibrary_typical.lib
# export LR_SYNTH_CELL_LIBRARY_NAME=nangate

View file

@ -4,50 +4,56 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
# This script converts all SystemVerilog RTL files to Verilog and then
# runs Yosys for ibex_core
#
# The following tools are required:
# - sv2v: SystemVerilog-to-Verilog converter from github.com/zachjs/sv2v
# - yosys: synthesis tool from github.com/YosysHQ/yosys
#
# Usage:
# syn_yosys.sh 2>&1 | tee syn.std
#
# Above command generates two files:
# ibex_core_premap.v : premap netlist (before mapping it onto std. cells)
# ibex_core_netlist.v : final netlist
# This script drives the experimental Ibex synthesis flow. More details can be
# found in README.md
# TODO: below should be replaced by elegant fusesoc commands
if [ ! -f syn_setup.sh ]; then
echo "Must provide syn_setup.sh file"
echo "See example in syn_setup.example.sh and README.md for instructions"
exit 1
fi
#-------------------------------------------------------------------------
# setup flow variables
#-------------------------------------------------------------------------
source syn_setup.sh
#-------------------------------------------------------------------------
# use sv2v to convert all SystemVerilog files to Verilog
#-------------------------------------------------------------------------
rm -Rf syn_out
mkdir syn_out
mkdir -p "$LR_SYNTH_OUT_DIR/generated"
mkdir -p "$LR_SYNTH_OUT_DIR/log"
mkdir -p "$LR_SYNTH_OUT_DIR/reports/timing"
for file in ../rtl/*.sv; do
module=`basename -s .sv $file`
sv2v \
--define=SYNTHESIS \
../rtl/*_pkg.sv \
../shared/rtl/prim_assert.sv \
$file \
> syn_out/${module}.v
> $LR_SYNTH_OUT_DIR/generated/${module}.v
# TODO: eventually remove below hack. It removes "unsigned" from params
# because Yosys doesn't support unsigned parameters
sed -i 's/parameter unsigned/parameter/g' syn_out/${module}.v
sed -i 's/localparam unsigned/localparam/g' syn_out/${module}.v
sed -i 's/parameter unsigned/parameter/g' $LR_SYNTH_OUT_DIR/generated/${module}.v
sed -i 's/localparam unsigned/localparam/g' $LR_SYNTH_OUT_DIR/generated/${module}.v
sed -i 's/reg unsigned/reg/g' $LR_SYNTH_OUT_DIR/generated/${module}.v
done
# remove generated *pkg.v files (they are empty files and not needed)
rm -f syn_out/*_pkg.v
rm -f $LR_SYNTH_OUT_DIR/generated/*_pkg.v
# remove tracer (not needed for synthesis)
rm -f $LR_SYNTH_OUT_DIR/generated/ibex_tracer.v
# remove the latch-based register file (because we will use the
# flop-based one instead)
rm -f syn_out/ibex_register_file_latch.v
rm -f $LR_SYNTH_OUT_DIR/generated/ibex_register_file_latch.v
#-------------------------------------------------------------------------
# run yosys
#-------------------------------------------------------------------------
yosys syn.ys -l syn.log
yosys -c ./tcl/yosys_run_synth.tcl | tee ./$LR_SYNTH_OUT_DIR/log/syn.log
sta ./tcl/sta_run_reports.tcl | tee ./$LR_SYNTH_OUT_DIR/log/sta.log
./translate_timing_rpts.sh

124
syn/tcl/flow_utils.tcl Normal file
View file

@ -0,0 +1,124 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
proc print_lr_synth_banner {} {
puts { _ ______ _____ _____ _____ }
puts {| | | ___ \|_ _|/ ___|/ __ \ }
puts {| | ___ __ __| |_/ / | | \ `--. | / \/ }
puts {| | / _ \ \ \ /\ / /| / | | `--. \| | }
puts {| || (_) | \ V V / | |\ \ _| |_ /\__/ /| \__/\ }
puts {|_| \___/ \_/\_/ \_| \_| \___/ \____/ \____/ }
puts { }
puts { }
puts { _ _ }
puts { | | | | }
puts { ___ _ _ _ __ | |_ | |__ }
puts { / __|| | | || '_ \ | __|| '_ \ }
puts { \__ \| |_| || | | || |_ | | | | }
puts { |___/ \__, ||_| |_| \__||_| |_| }
puts { __/ | }
puts { |___/ }
puts {}
puts {****** o p e n t o t h e c o r e ******* }
puts {}
}
proc print_yosys_banner {} {
puts { +---------------------------------+}
puts { | _ _ ___ ___ _ _ ___ |}
puts { | | | | | / _ \ / __|| | | |/ __| |}
puts { | | |_| || (_) |\__ \| |_| |\__ \ |}
puts { | \__, | \___/ |___/ \__, ||___/ |}
puts { | __/ | __/ | |}
puts { | |___/ |___/ |}
puts { +---------------------------------+}
puts {}
}
proc print_opensta_banner {} {
puts {+--------------------------------------------------+}
puts {| _____ _____ _____ ___ |}
puts {| | _ | / ___||_ _| / _ \ |}
puts {| | | | | _ __ ___ _ __ \ `--. | | / /_\ \ |}
puts {| | | | || '_ \ / _ \| '_ \ `--. \ | | | _ | |}
puts {| \ \_/ /| |_) || __/| | | |/\__/ / | | | | | | |}
puts {| \___/ | .__/ \___||_| |_|\____/ \_/ \_| |_/ |}
puts {| | | |}
puts {| |_| |}
puts {+--------------------------------------------------+}
puts {}
}
proc set_flow_var {var_name var_default var_friendly_name} {
global lr_synth_flow_var_quiet
set var_name "lr_synth_${var_name}"
global $var_name
set env_var_name [string toupper $var_name]
if { [info exists ::env($env_var_name)] } {
set $var_name $::env($env_var_name)
puts "$var_friendly_name: $::env($env_var_name)"
} else {
set $var_name $var_default
puts "$var_friendly_name: $var_default (default)"
}
}
proc set_flow_bool_var {var_name var_default var_friendly_name} {
global lr_synth_flow_var_quiet
set var_name "lr_synth_${var_name}"
global $var_name
set env_var_name [string toupper $var_name]
if { [info exists ::env($env_var_name)] } {
if { $::env($env_var_name) } {
set $var_name 1
} else {
set $var_name 0
}
} else {
set $var_name $var_default
}
if { [set $var_name] } {
puts "$var_friendly_name: Enabled"
} else {
puts "$var_friendly_name: Disabled"
}
}
proc write_sdc_out {sdc_file_in sdc_file_out} {
global lr_synth_clk_period
global lr_synth_clk_input
global lr_synth_outputs
global lr_synth_inputs
set sdc_out [open $sdc_file_out "w"]
set sdc_in [open $sdc_file_in "r"]
set sdc_in_contents [read $sdc_in]
puts $sdc_out $sdc_in_contents
puts $sdc_out "#============ Auto-generated from config ============"
set clk_period_ns [expr $lr_synth_clk_period / 1000.0]
puts $sdc_out "create_clock -name $lr_synth_clk_input -period $clk_period_ns {$lr_synth_clk_input}"
foreach output $lr_synth_outputs {
set output_constraint [lindex $output 1]
set output_constraint [expr (1.0 - ($output_constraint / 100.0)) * $clk_period_ns]
puts $sdc_out "set_output_delay -clock $lr_synth_clk_input $output_constraint [lindex $output 0]"
}
foreach input $lr_synth_inputs {
set input_constraint [lindex $input 1]
set input_constraint [expr ($input_constraint / 100.0) * $clk_period_ns]
puts $sdc_out "set_input_delay -clock $lr_synth_clk_input $input_constraint [lindex $input 0]"
}
close $sdc_out
close $sdc_in
}

View file

@ -0,0 +1,48 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
puts "=================== Flow Vars ==================="
set_flow_var cell_library_path "cmos_cells.lib" "Path to cell library"
set_flow_var top_module "ibex_core" "top module"
set_flow_var out_dir "syn_out" "Output directory for synthesis"
set_flow_var pre_map_out "./${lr_synth_out_dir}/generated/${lr_synth_top_module}.pre_map.v" "Pre-mapping netlist out"
set_flow_var netlist_out "./${lr_synth_out_dir}/generated/${lr_synth_top_module}_netlist.v" "netlist out"
set_flow_var config_file "${lr_synth_top_module}_lr_synth_conf.tcl" "Synth config file"
set_flow_var rpt_out "./${lr_synth_out_dir}/reports" "Report output directory"
set_flow_bool_var flatten 1 "flatten"
set_flow_bool_var timing_run 0 "timing run"
source $lr_synth_config_file
if { $lr_synth_timing_run } {
set_flow_var cell_library_name "nangate" "Name of cell library"
#set_flow_var sdc_file "${top_module}.sdc" "SDC file"
set_flow_var sdc_file_in "${lr_synth_top_module}.${lr_synth_cell_library_name}.sdc" "Input SDC file"
set flop_in_pin_default "*/D"
set flop_out_pin_default "*/Q"
# STA needs to know start and end points for identifying reg2reg paths. These
# can vary depending upon the library used
if { [string first "nangate" $lr_synth_cell_library_name] == 0 } {
set flop_in_pin_default "*/D"
set flop_out_pin_default "*/CK"
}
set_flow_var flop_in_pin $flop_in_pin_default "In pin to flop for reg2reg path extraction"
set_flow_var flop_out_pin $flop_out_pin_default "Out pin from flop for reg2reg path extraction"
set sdc_file_out_default [string range $lr_synth_sdc_file_in 0 [expr [string last ".sdc" $lr_synth_sdc_file_in] - 1]]
set sdc_file_out_default "./${lr_synth_out_dir}/generated/$sdc_file_out_default.out.sdc"
set_flow_var sdc_file_out $sdc_file_out_default "Output SDC file"
set sta_netlist_out_default [string range $lr_synth_netlist_out 0 [expr [string last ".v" $lr_synth_netlist_out] - 1]]
set sta_netlist_out_default "$sta_netlist_out_default.sta.v"
set_flow_var sta_netlist_out $sta_netlist_out_default "STA netlist out"
set_flow_var sta_paths_per_group 100 "STA paths reported per group"
set_flow_var sta_overall_paths 1000 "STA paths reported in overall report"
puts "clock period: $lr_synth_clk_period ps"
}
puts "================================================="

18
syn/tcl/sta_common.tcl Normal file
View file

@ -0,0 +1,18 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
source ./tcl/flow_utils.tcl
source ./tcl/lr_synth_flow_var_setup.tcl
source ./tcl/sta_utils.tcl
print_lr_synth_banner
print_opensta_banner
read_liberty $lr_synth_cell_library_path
read_verilog $lr_synth_sta_netlist_out
link_design $lr_synth_top_module
read_sdc $lr_synth_sdc_file_out

View file

@ -0,0 +1,6 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
source ./tcl/sta_common.tcl

View file

@ -0,0 +1,21 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
source ./tcl/sta_common.tcl
set overall_rpt_file "${lr_synth_rpt_out}/timing/overall"
timing_report $lr_synth_clk_input $overall_rpt_file $lr_synth_sta_overall_paths
set lr_synth_path_group_list [list]
setup_path_groups $lr_synth_inputs $lr_synth_outputs lr_synth_path_group_list
foreach path_group $lr_synth_path_group_list {
puts $path_group
set path_group_rpt_file "${lr_synth_rpt_out}/timing/$path_group"
timing_report $path_group $path_group_rpt_file $lr_synth_sta_paths_per_group
}
exit

53
syn/tcl/sta_utils.tcl Normal file
View file

@ -0,0 +1,53 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
proc setup_path_groups {input_list output_list path_group_list_name} {
upvar $path_group_list_name path_group_list
foreach output $output_list {
set output_name [lindex $output 0]
set output_ports [get_ports $output_name]
set path_group_name "x2out_${output_name}"
group_path -name $path_group_name -to $output_ports
lappend path_group_list $path_group_name
}
foreach input $input_list {
set input_name [lindex $input 0]
set input_ports [get_ports $input_name]
set path_group_name "in2x_${input_name}"
group_path -name $path_group_name -from $input_ports
lappend path_group_list $path_group_name
}
global lr_synth_flop_in_pin
global lr_synth_flop_out_pin
set flops_in [get_pins $lr_synth_flop_in_pin]
set flops_out [get_pins $lr_synth_flop_out_pin]
group_path -name "reg2reg" -to $flops_in -from $flops_out
lappend path_group_list "reg2reg"
}
proc timing_report {path_group rpt_out path_count} {
set sta_report_out_filename "${rpt_out}.rpt"
set sta_csv_out_filename "${rpt_out}.csv.rpt"
puts "Reporting $path_group to $sta_report_out_filename and $sta_csv_out_filename"
report_checks -group_count $path_count -path_group $path_group > $sta_report_out_filename
set paths [find_timing_paths -group_count $path_count -path_group $path_group]
set sta_csv_out [open $sta_csv_out_filename "w"]
foreach path $paths {
set startpoint_name [get_name [get_property $path startpoint]]
set endpoint_name [get_name [get_property $path endpoint]]
set slack [get_property $path slack]
puts $sta_csv_out [format "$startpoint_name,$endpoint_name,%.4f" $slack]
}
close $sta_csv_out
}

12
syn/tcl/yosys_common.tcl Normal file
View file

@ -0,0 +1,12 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
source ./tcl/flow_utils.tcl
print_lr_synth_banner
print_yosys_banner
source ./tcl/lr_synth_flow_var_setup.tcl
yosys "read_liberty -lib $lr_synth_cell_library_path"

View file

@ -0,0 +1,10 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
source ./tcl/yosys_common.tcl
yosys "read_liberty -lib $lr_synth_cell_library_path"
yosys "read_verilog $lr_synth_netlist_out"

View file

@ -0,0 +1,9 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
source ./tcl/yosys_common.tcl
yosys "read_liberty -lib $lr_synth_cell_library_path"
yosys "read_verilog $lr_synth_pre_map_out"

View file

@ -0,0 +1,47 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
source ./tcl/yosys_common.tcl
if { $lr_synth_flatten } {
set flatten_opt "-flatten"
} else {
set flatten_opt ""
}
if { $lr_synth_timing_run } {
write_sdc_out $lr_synth_sdc_file_in $lr_synth_sdc_file_out
}
yosys "read -sv ./rtl/prim_clock_gating.v $lr_synth_out_dir/generated/*.v"
yosys "synth $flatten_opt -top $lr_synth_top_module"
yosys "opt -purge"
yosys "write_verilog $lr_synth_pre_map_out"
yosys "dfflibmap -liberty $lr_synth_cell_library_path"
yosys "opt"
if { $lr_synth_timing_run } {
yosys "abc -liberty $lr_synth_cell_library_path -constr $lr_synth_sdc_file_out -D $lr_synth_clk_period"
} else {
yosys "abc -liberty $lr_synth_cell_library_path"
}
yosys "clean"
yosys "write_verilog $lr_synth_netlist_out"
if { $lr_synth_timing_run } {
# Produce netlist that OpenSTA can use
yosys "setundef -zero"
yosys "splitnets"
yosys "write_verilog -noattr -noexpr -nohex -nodec $lr_synth_sta_netlist_out"
}
yosys "check"
yosys "log ======== Yosys Stat Report ========"
yosys "tee -o $lr_synth_out_dir/reports/area.rpt stat -liberty $lr_synth_cell_library_path"
yosys "log ====== End Yosys Stat Report ======"

12
syn/translate_timing_rpts.sh Executable file
View file

@ -0,0 +1,12 @@
#!/bin/bash
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
./python/build_translated_names.py ibex_core ./$LR_SYNTH_OUT_DIR/generated ./$LR_SYNTH_OUT_DIR/reports/timing/*.csv.rpt
for file in ./$LR_SYNTH_OUT_DIR/reports/timing/*.csv.rpt; do
./python/translate_timing_csv.py $file ./$LR_SYNTH_OUT_DIR/generated
done