Skip to content

Commit

Permalink
Merge pull request #88 from nanavati/yosys-step
Browse files Browse the repository at this point in the history
Add a rule for creating single-file Yosys synthesis steps
  • Loading branch information
nanavati authored Feb 3, 2022
2 parents 0dfa1dd + 0084458 commit 216554a
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 1 deletion.
11 changes: 10 additions & 1 deletion flows/flows.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@ def _run_step_with_inputs(ctx, step, inputs_dict, outputs_step_dict):

return dicts.add(inputs_dict, outputs_dict)

def target_to_file(target):
all_files = target.files.to_list()
if len(all_files) != 1:
fail("Input target", target, "should provide exactly one file instead of", all_files)

return all_files[0]

def _run_flow_impl(ctx):
if len(ctx.attr.output_names) != len(ctx.outputs.output_files):
fail(
Expand Down Expand Up @@ -249,7 +256,9 @@ def _run_flow_impl(ctx):
"lists should have the same length",
)

inputs_dict = dict(zip(ctx.attr.input_names, ctx.attr.input_files))
input_files = [target_to_file(target) for target in ctx.attr.input_files]

inputs_dict = dict(zip(ctx.attr.input_names, input_files))

for step in ctx.attr.flow:
inputs_dict = _run_step_with_inputs(ctx, step, inputs_dict, outputs_step_dict)
Expand Down
35 changes: 35 additions & 0 deletions flows/tests/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

# Modular hardware flow tests

load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
load("//flows:flows.bzl", "flow_binary", "run_flow")
load("//flows/place_and_route:build_defs.bzl", "openroad_step")
Expand Down Expand Up @@ -58,3 +59,37 @@ flow_binary(
"goodbye_openroad",
],
)

run_flow(
name = "synth_sky130_adder",
constants = {"top": "adder"},
flow = ["//flows/yosys:synth_sky130"],
input_files = ["verilog_adder.v"],
input_names = ["rtl"],
output_files = ["sky130_adder_test.v"],
output_names = ["netlist"],
)

# TODO(amfv): This only tests that adding the clock period constant
# does not break synthesis. Figure out how to test that the clock
# period is actually used properly.
run_flow(
name = "synth_sky130_adder_with_clock_period",
constants = {
"clock_period_ps": "2000",
"top": "adder",
},
flow = ["//flows/yosys:synth_sky130"],
input_files = ["verilog_adder.v"],
input_names = ["rtl"],
output_files = ["sky130_adder_with_clock_period_test.v"],
output_names = ["netlist"],
)

build_test(
name = "synth_sky130_smoke",
targets = [
":synth_sky130_adder",
":synth_sky130_adder_with_clock_period",
],
)
24 changes: 24 additions & 0 deletions flows/tests/verilog_adder.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//Copyright 2021 Google LLC
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.


module adder(
input [7:0] x,
input [7:0] y,
input carry_in,
output carry_output_bit,
output [7:0] sum,
);
assign {carry_output_bit, sum} = x + y + carry_in;
endmodule
40 changes: 40 additions & 0 deletions flows/yosys/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Yosys synthesis step for modular flows.

load("@rules_pkg//:pkg.bzl", "pkg_tar")
load("//flows:flows.bzl", "flow_binary")
load("//flows/yosys:build_defs.bzl", "yosys_synth_file_step")

package(default_visibility = ["//flows:__subpackages__"])

exports_files(["synth.tcl"])

yosys_synth_file_step(
name = "synth_sky130",
standard_cells = "@com_google_skywater_pdk_sky130_fd_sc_hd//:sky130_fd_sc_hd",
)

flow_binary(
name = "synth_sky130_bin",
flow = ["synth_sky130"],
)

pkg_tar(
name = "synth_sky130_pkg",
srcs = [":synth_sky130_bin"],
include_runfiles = True,
strip_prefix = "./",
)
97 changes: 97 additions & 0 deletions flows/yosys/build_defs.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Reimplementing place-and-route using composable and externalizable pieces"""

load("//flows:flows.bzl", "FlowStepInfo", "script_prefix")
load("//pdk:build_defs.bzl", "StandardCellInfo")

def _yosys_synth_file_step_impl(ctx):
yosys_executable = ctx.attr._yosys.files_to_run.executable
yosys_runfiles = ctx.attr._yosys[DefaultInfo].default_runfiles

yosys_wrapper = ctx.actions.declare_file(ctx.attr.name)

standard_cells = ctx.attr.standard_cells[StandardCellInfo]

liberty = standard_cells.default_corner.liberty

synth_tcl = ctx.file.synth_tcl

cell_runfiles = ctx.runfiles(files = [synth_tcl, liberty, yosys_wrapper])

yosys_args = [
"-q", # quiet mode only errors printed to stderr
"-q", # second q don't print warnings
"-Q", # Don't print header
"-T", # Don't print footer
"-c ${RUNFILES}/" + synth_tcl.short_path,
]

commands = [script_prefix]
commands.append("export LIBERTY=${RUNFILES}/" + liberty.short_path)

# TODO(amfv): Compute Yosys data environment variables properly instead of hardcoding them.
commands.extend([
"export YOSYS_DATDIR=${RUNFILES}/../at_clifford_yosys/techlibs/",
"export ABC=${RUNFILES}/../edu_berkeley_abc/abc",
])

exec_yosys = """{yosys} {args} "$@"\n""".format(
yosys = "${RUNFILES}/" + yosys_executable.short_path,
args = " ".join(yosys_args),
)

commands.append(exec_yosys)

ctx.actions.write(
output = yosys_wrapper,
content = "\n".join(commands) + "\n",
is_executable = True,
)

return [
FlowStepInfo(
inputs = ["rtl"],
outputs = ["netlist"],
constants = ["top"], # , "clock_period"],
executable_type = "yosys",
arguments = [],
),
DefaultInfo(
executable = yosys_wrapper,
# TODO(amfv): Switch to runfiles.merge_all once our minimum Bazel version provides it.
runfiles = cell_runfiles.merge(yosys_runfiles),
),
]

yosys_synth_file_step = rule(
implementation = _yosys_synth_file_step_impl,
attrs = {
"_yosys": attr.label(
default = Label("@at_clifford_yosys//:yosys"),
executable = True,
cfg = "exec",
),
"standard_cells": attr.label(
doc = "Standard cells to use in yosys synthesis step",
providers = [StandardCellInfo],
),
"synth_tcl": attr.label(
default = Label("//flows/yosys:synth.tcl"),
allow_single_file = True,
doc = "Tcl script controlling Yosys synthesis, using the Flow Step API environment variables",
),
},
)
30 changes: 30 additions & 0 deletions flows/yosys/synth.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Default Yosys synthesis tcl script for the yosys_synth_file_step rule.
# It can be replaced by a user-defined script by overriding the synth_tcl
# argument of that rule.

yosys -import

# read design
set input_rtl $::env(INPUT_RTL)
yosys read_verilog -sv -defer $input_rtl

# generic synthesis
set top $::env(CONSTANT_TOP)
yosys synth -top $top

# mapping to liberty
set liberty $::env(LIBERTY)
dfflibmap -liberty $liberty

if { [info exists ::env(CONSTANT_CLOCK_PERIOD_PS) ] } {
abc -liberty $liberty -dff -g aig -D $::env(CONSTANT_CLOCK_PERIOD_PS)
} else {
abc -liberty $liberty -dff -g aig
}

# write synthesized design
set output $::env(OUTPUT_NETLIST)
write_verilog $output

# print stats
stat

0 comments on commit 216554a

Please sign in to comment.