Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
[submodule "chipcompiler/thirdparty/ecc-dreamplace"]
path = chipcompiler/thirdparty/ecc-dreamplace
url = https://github.com/openecos-projects/ecc-dreamplace.git
[submodule "test/icsprout55-pdk"]
path = test/icsprout55-pdk
url = git@github.com:openecos-projects/icsprout55-pdk.git
Comment thread
Copilot marked this conversation as resolved.
Outdated
3 changes: 3 additions & 0 deletions chipcompiler/data/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@
"Top module": "gcd",
"Clock": "clk",
"Frequency max [MHz]": 100,
"LEC": {
"use_undef": True,
},
}
}

Expand Down
4 changes: 3 additions & 1 deletion chipcompiler/data/step.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class StepEnum(Enum):
FILLER = "filler"
GDS = "GDS"
SIGNOFF = "Signoff"
LEC = "lec"
POST_ROUTE_LEC = "postRouteLec"
STA = "sta"
DRC = "drc"
RCX = "RCX"
Expand Down Expand Up @@ -83,4 +85,4 @@ def load_metrics(path : str) -> StepMetrics:
def save_metrics(metrics : StepMetrics) -> bool:
from chipcompiler.utility import json_write
return json_write(file_path=metrics.path,
data=metrics.data)
data=metrics.data)
30 changes: 26 additions & 4 deletions chipcompiler/engine/flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ def has_init(self):
def init_flow_step(self,
step : StepEnum | str,
tool : str,
state : str | StateEnum):
state : str | StateEnum,
info: dict | None = None):
step_value = step.value if isinstance(step, StepEnum) else step
state_value = state.value if isinstance(state, StateEnum) else state
return {
Expand All @@ -60,15 +61,16 @@ def init_flow_step(self,
"state" : state_value, # step state
"runtime" : "", # step run time
"peak memory (mb)" : 0, # step peak memory
"info" : {} # step additional infomation
"info" : info or {} # step additional infomation
}

def add_step(self,
step : StepEnum | str,
tool : str,
state : str | StateEnum):
state : str | StateEnum,
info: dict | None = None):
steps = self.workspace.flow.data.get("steps", [])
steps.append(self.init_flow_step(step, tool, state))
steps.append(self.init_flow_step(step, tool, state, info=info))

self.workspace.flow.data = {"steps" : steps}

Expand Down Expand Up @@ -172,6 +174,11 @@ def check_step_result(self,
"""
import os
success = False
if (
workspace_step.tool == "yosys_lec"
or workspace_step.name in (StepEnum.LEC.value, StepEnum.POST_ROUTE_LEC.value)
):
return os.path.exists(workspace_step.output.get("json", ""))
Comment on lines +177 to +181

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer to use match:

Suggested change
if (
workspace_step.tool == "yosys_lec"
or workspace_step.name in (StepEnum.LEC.value, StepEnum.POST_ROUTE_LEC.value)
):
return os.path.exists(workspace_step.output.get("json", ""))
match (workspace_step.tool, workspace_step.name):
case ("yosys_lec", _) | (_, StepEnum.LEC.value) | (_, StepEnum.POST_ROUTE_LEC.value):
return os.path.exists(workspace_step.output.get("json", ""))

match workspace_step.name:
case StepEnum.SYNTHESIS.value:
if os.path.exists(workspace_step.output.get("verilog", "")):
Expand All @@ -197,6 +204,8 @@ def create_step_workspaces(self):
create all step workspaces
"""
pre_step = None
synthesis_gate_verilog = ""
synthesis_golden_verilog = ""
for step in self.workspace.flow.data.get("steps", []):
if pre_step is None:
# use the origin def and verilog in workspace for the first step.
Expand All @@ -209,6 +218,16 @@ def create_step_workspaces(self):
input_verilog = pre_step.output.get("verilog", "")
input_db = pre_step.output.get("db", "")

if step["tool"] == "yosys_lec":
step_info = step.get("info", {}) or {}
explicit_golden = step_info.get("golden_verilog", "")
if explicit_golden:
input_db = explicit_golden
elif step["name"] == StepEnum.POST_ROUTE_LEC.value:
input_db = synthesis_gate_verilog
elif pre_step is not None and pre_step.name == StepEnum.SYNTHESIS.value:
input_db = synthesis_golden_verilog

from chipcompiler.tools import create_step, run_step
# create workspace step
eda_step = create_step(workspace=self.workspace,
Expand All @@ -225,6 +244,9 @@ def create_step_workspaces(self):
eda_step.output["spef"] = pre_step.output.get("spef", [])
self.workspace_steps.append(eda_step)
pre_step = eda_step
if eda_step.name == StepEnum.SYNTHESIS.value:
synthesis_gate_verilog = eda_step.output.get("verilog", "")
synthesis_golden_verilog = eda_step.output.get("golden_verilog", "")
else:
# error create step, TBD
pass
Expand Down
8 changes: 6 additions & 2 deletions chipcompiler/rtl2gds/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
from .builder import (
build_rtl2gds_flow,
build_harden_flow,
build_rcx_flow
build_rcx_flow,
build_synthesis_lec_flow,
build_post_route_lec_flow
)

__all__ = [
'build_rtl2gds_flow',
'build_harden_flow',
'build_rcx_flow'
'build_rcx_flow',
'build_synthesis_lec_flow',
'build_post_route_lec_flow'
]
23 changes: 23 additions & 0 deletions chipcompiler/rtl2gds/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,26 @@ def build_rcx_flow() -> list:
steps.append((StepEnum.STA, "ecc", StateEnum.Unstart))

return steps

def build_synthesis_lec_flow() -> list:
steps = []

steps.append((StepEnum.SYNTHESIS, "yosys", StateEnum.Unstart))
steps.append((StepEnum.LEC, "yosys_lec", StateEnum.Unstart))

return steps

def build_post_route_lec_flow() -> list:
steps = []

steps.append((StepEnum.SYNTHESIS, "yosys", StateEnum.Unstart))
steps.append((StepEnum.FLOORPLAN, "ecc", StateEnum.Unstart))
steps.append((StepEnum.NETLIST_OPT, "ecc", StateEnum.Unstart))
steps.append((StepEnum.PLACEMENT, "dreamplace", StateEnum.Unstart))
steps.append((StepEnum.CTS, "ecc", StateEnum.Unstart))
steps.append((StepEnum.LEGALIZATION, "dreamplace", StateEnum.Unstart))
steps.append((StepEnum.ROUTING, "ecc", StateEnum.Unstart))

steps.append((StepEnum.POST_ROUTE_LEC, "yosys_lec", StateEnum.Unstart))

return steps
3 changes: 3 additions & 0 deletions chipcompiler/tools/yosys/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ def generate_global_var_tcl(workspace: Workspace,

# Output files
set final_netlist_file {_tcl_quote(netlist_file)}
set golden_netlist_file {_tcl_quote(_abspath(step.output.get("golden_verilog", "")))}
Comment thread
Copilot marked this conversation as resolved.
Outdated
set timing_cell_stat_rpt {_tcl_quote(timing_cell_stat_rpt)}
set timing_cell_count_rpt {_tcl_quote(timing_cell_count_rpt)}
set generic_stat_json {_tcl_quote(generic_stat_json)}
Expand Down Expand Up @@ -180,12 +181,14 @@ def build_step(workspace: Workspace,

if output_verilog is None:
output_verilog = f"{step.directory}/output/{workspace.design.name}_{step.name}.v"
golden_verilog = f"{step.directory}/output/{workspace.design.name}_{step_name}_golden.v"
if output_def is None:
output_def = f"{step.directory}/output/{workspace.design.name}_{step.name}.def.gz"
step.output = {
"dir": f"{step.directory}/output",
"def": output_def,
"verilog": output_verilog,
"golden_verilog": golden_verilog,
"fixed_verilog": f"{step.directory}/output/{workspace.design.name}_{step.name}_fixed.v",
"json": f"{step.directory}/output/{workspace.design.name}_{step.name}.json",
"report": f"{step.directory}/output/{workspace.design.name}_{step.name}.rpt",
Expand Down
9 changes: 7 additions & 2 deletions chipcompiler/tools/yosys/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ def run_step(workspace: Workspace,
stderr=subprocess.STDOUT,
)

if os.path.exists(step.output["verilog"]):
output_exists = os.path.exists(step.output["verilog"])
golden_path = step.output.get("golden_verilog", "")
golden_exists = not golden_path or os.path.exists(golden_path)

if output_exists and golden_exists:
sub_flow.update_step(step_name="run yosys", state=StateEnum.Success)

fixed_netlist = step.output.get("fixed_verilog", "")
Expand All @@ -140,7 +144,8 @@ def run_step(workspace: Workspace,
sub_flow.update_step(step_name="run yosys", state=StateEnum.Invalid)

print(
f"Error: Output netlist not generated at {step.output['verilog']}. "
f"Error: Output netlist not generated at {step.output['verilog']} "
f"or golden netlist not generated at {golden_path}. "
f"yosys exit code: {result.returncode}"
)
return False
Expand Down
4 changes: 4 additions & 0 deletions chipcompiler/tools/yosys/scripts/yosys_synthesis.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ yosys select -write ${timing_cell_stat_rpt} t:*DFF*
yosys tee -q -o ${timing_cell_count_rpt} select -count t:*DFF*
yosys tee -q -a ${timing_cell_count_rpt} select -count */t:*_DLATCH*_ */t:*_SR*_

if {[info exists golden_netlist_file] && $golden_netlist_file ne ""} {
yosys write_verilog -noattr -noexpr -nohex -nodec ${golden_netlist_file}
}

# yosys tee -q -o "${generic_stat_json}" stat -json -tech cmos
# yosys tee -q -o "${generic_stat_json}.rpt" stat -tech cmos
# -----------------------------------------------------------------------------
Expand Down
18 changes: 18 additions & 0 deletions chipcompiler/tools/yosys_lec/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from .builder import (
build_step,
build_step_space,
build_step_config,
)

from .runner import run_step
from .subflow import YosysLecSubFlow
from .utility import is_eda_exist

__all__ = [
"is_eda_exist",
"build_step",
"build_step_space",
"build_step_config",
"run_step",
"YosysLecSubFlow",
]
Loading
Loading