Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Group LRAM timings by cell configuration #29

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
65 changes: 0 additions & 65 deletions timing/fuzzers/LIFCL/02-ram/gen_ram.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ def get_next_data(i, N):
return ["d_{}[{}]".format(i, j) for j in range(N)]

N = 80
M = 2

for i in range(N):
prim = random.choice(["DP16K", "PDP16K", "PDPSC16K", "SP16K", "FIFO16K"])
Expand Down Expand Up @@ -118,69 +117,5 @@ def get_next_data(i, N):
assert False
data = next_data

for i in range(N, N+M):
lram_prim = random.choice(["DPSC512K", "PDPSC512K", "SP512K"])
if lram_prim == "DPSC512K":
next_data = get_next_data(i, 32+32+4)
print(" DPSC512K lram_{} (".format(i))
clock_port("CLK")
ce_port("CEA")
ce_port("CEB")
ce_port("WEA")
ce_port("WEB")
ce_port("CSA")
ce_port("CSB")
ce_port("CEOUTA")
ce_port("CEOUTB")
rst_port("RSTA")
rst_port("RSTB")
data_port("BENA_N", 4)
data_port("BENB_N", 4)
data_port("ADA", 14)
data_port("ADB", 14)
data_port("DIA", 32)
data_port("DIB", 32)
output_port("DOA", i, 0, 32, False)
output_port("DOB", i, 32, 32, False)
output_port("ERRDECA", i, 64, 2, False)
output_port("ERRDECB", i, 66, 2, True)
print(" );")
elif lram_prim == "PDPSC512K":
next_data = get_next_data(i, 32+4)
print(" PDPSC512K lram_{} (".format(i))
clock_port("CLK")
ce_port("CEW")
ce_port("CER")
ce_port("WE")
ce_port("CSW")
ce_port("CSR")
rst_port("RSTR")
data_port("BYTEEN_N", 4)
data_port("ADW", 14)
data_port("ADR", 14)
data_port("DI", 32)
output_port("DO", i, 0, 32, False)
output_port("ERRDECA", i, 32, 2, False)
output_port("ERRDECB", i, 34, 2, True)
print(" );")
elif lram_prim == "SP512K":
next_data = get_next_data(i, 32+4)
print(" SP512K lram_{} (".format(i))
clock_port("CLK")
ce_port("CE")
ce_port("WE")
ce_port("CS")
ce_port("CEOUT")
rst_port("RSTOUT")
data_port("BYTEEN_N", 4)
data_port("AD", 14)
data_port("DI", 32)
output_port("DO", i, 0, 32, False)
output_port("ERRDECA", i, 32, 2, False)
output_port("ERRDECB", i, 34, 2, True)
print(" );")
else:
assert False
data = next_data
print(" assign q = {};".format(data_bits(8)))
print("endmodule")
7 changes: 7 additions & 0 deletions timing/fuzzers/LIFCL/09-lram/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
NAME=lram
RUNS=$(shell seq 10)
GENERATOR2=gen_lram.py
DEVICE=LIFCL-17
ALLOW_FAIL=false

include ../../../tools/fuzzer.mk
151 changes: 151 additions & 0 deletions timing/fuzzers/LIFCL/09-lram/gen_lram.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import argparse
import random
import json

def main():

parser = argparse.ArgumentParser()
parser.add_argument(
"--vlog",
type=str,
required=True,
help="Output Verilog file"
)
parser.add_argument(
"--conf",
type=str,
required=True,
help="Output cell configuration file"
)

args = parser.parse_args()

vlog = open(args.vlog, "w")

print("module top(input [3:0] clk, ce, rst, input [7:0] d, output [7:0] q);", file=vlog)
data = ["d[{}]".format(i) for i in range(8)]

def data_bits(N):
return "{{{}}}".format(", ".join([random.choice(data) for i in range(N)]))
def clock_port(name):
print(" .{}(clk[{}]),".format(name, random.randint(0, 3)), file=vlog)
def ce_port(name):
print(" .{}(ce[{}]),".format(name, random.randint(0, 3)), file=vlog)
def rst_port(name):
print(" .{}(rst[{}]),".format(name, random.randint(0, 3)), file=vlog)
def data_port(name, N):
print(" .{}({}),".format(name, data_bits(N)), file=vlog)
def output_port(name, i, j, N, last=False):
print(" .{}(d_{}[{} +: {}]){}".format(name, i, j, N, "" if last else ","), file=vlog)

def get_next_data(i, N):
print(" wire [{}:0] d_{};".format(N-1, i), file=vlog)
return ["d_{}[{}]".format(i, j) for j in range(N)]

N = 5
config = {}

for i in range(N):
lram_prim = random.choice(["DPSC512K", "PDPSC512K", "SP512K"])
if lram_prim == "DPSC512K":
oreg_a = random.choice(["NO_REG", "OUT_REG"])
oreg_b = random.choice(["NO_REG", "OUT_REG"])
next_data = get_next_data(i, 32+32+4)
print(" DPSC512K #(.OUTREG_A(\"{}\"),.OUTREG_B(\"{}\")) lram_{} (".format(oreg_a, oreg_b, i), file=vlog)
clock_port("CLK")
ce_port("CEA")
ce_port("CEB")
ce_port("WEA")
ce_port("WEB")
ce_port("CSA")
ce_port("CSB")
ce_port("CEOUTA")
ce_port("CEOUTB")
rst_port("RSTA")
rst_port("RSTB")
data_port("BENA_N", 4)
data_port("BENB_N", 4)
data_port("ADA", 14)
data_port("ADB", 14)
data_port("DIA", 32)
data_port("DIB", 32)
output_port("DOA", i, 0, 32, False)
output_port("DOB", i, 32, 32, False)
output_port("ERRDECA", i, 64, 2, False)
output_port("ERRDECB", i, 66, 2, True)
print(" );", file=vlog)

key = f"lram_{i}"
config[key] = {
"type": "DPC512K",
"params": {
"OUTREG_A": oreg_a,
"OUTREG_B": oreg_b,
},
}

elif lram_prim == "PDPSC512K":
oreg = random.choice(["NO_REG", "OUT_REG"])
next_data = get_next_data(i, 32+4)
print(" PDPSC512K #(.OUTREG(\"{}\")) lram_{} (".format(oreg, i), file=vlog)
clock_port("CLK")
ce_port("CEW")
ce_port("CER")
ce_port("WE")
ce_port("CSW")
ce_port("CSR")
rst_port("RSTR")
data_port("BYTEEN_N", 4)
data_port("ADW", 14)
data_port("ADR", 14)
data_port("DI", 32)
output_port("DO", i, 0, 32, False)
output_port("ERRDECA", i, 32, 2, False)
output_port("ERRDECB", i, 34, 2, True)
print(" );", file=vlog)

key = f"lram_{i}"
config[key] = {
"type": "PDPSC512K",
"params": {
"OUTREG": oreg,
},
}

elif lram_prim == "SP512K":
oreg = random.choice(["NO_REG", "OUT_REG"])
next_data = get_next_data(i, 32+4)
print(" SP512K #(.OUTREG(\"{}\")) lram_{} (".format(oreg, i), file=vlog)
clock_port("CLK")
ce_port("CE")
ce_port("WE")
ce_port("CS")
ce_port("CEOUT")
rst_port("RSTOUT")
data_port("BYTEEN_N", 4)
data_port("AD", 14)
data_port("DI", 32)
output_port("DO", i, 0, 32, False)
output_port("ERRDECA", i, 32, 2, False)
output_port("ERRDECB", i, 34, 2, True)
print(" );", file=vlog)

key = f"lram_{i}"
config[key] = {
"type": "SP512K",
"params": {
"OUTREG": oreg,
},
}

else:
assert False
data = next_data
print(" assign q = {};".format(data_bits(8)), file=vlog)
print("endmodule", file=vlog)

with open(args.conf, "w") as fp:
fp.write(json.dumps(config, sort_keys=True, indent=2))

if __name__ == "__main__":
main()
16 changes: 14 additions & 2 deletions timing/tools/fuzzer.mk
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
PYTHON ?= python3

all: work/stamp

work/stamp: $(foreach run,$(RUNS),work/$(run).stamp)
Expand All @@ -6,17 +8,25 @@ work/stamp: $(foreach run,$(RUNS),work/$(run).stamp)
BASE_DIR=../../../../
OUT_DIR=../../../output/

ifneq ($(GENERATOR),)
work/design_%.v: $(GENERATOR)
mkdir -p work/
python $(GENERATOR) > $@
$(PYTHON) $(GENERATOR) > $@
endif

ifneq ($(GENERATOR2),)
work/design_%.v: $(GENERATOR2)
mkdir -p work/
$(PYTHON) $(GENERATOR2) --vlog $@ --conf $(subst .v,.json,$@)
endif

work/design_%.bit: work/design_%.v
$(BASE_DIR)/radiant.sh $(DEVICE) $< || $(ALLOW_FAIL)

work/%.stamp: work/design_%.bit
mkdir -p $(OUT_DIR)

python $(BASE_DIR)/timing/util/extract_route.py work/design_$*.tmp/par.udb $(OUT_DIR)/$(NAME)_$*_route.pickle
$(PYTHON) $(BASE_DIR)/timing/util/extract_route.py work/design_$*.tmp/par.udb $(OUT_DIR)/$(NAME)_$*_route.pickle

# we need the '|| true' because of
# malloc_consolidate(): unaligned fastbin chunk detected
Expand All @@ -31,6 +41,8 @@ work/%.stamp: work/design_%.bit

$(BASE_DIR)/radiant_cmd.sh backanno -min -w -o $(OUT_DIR)/$(NAME)_$*_M.vo work/design_$*.tmp/par.udb || true

[ -f "work/design_$*.json" ] && cp -f "work/design_$*.json" $(OUT_DIR)/$(NAME)_$*.json

touch $@

.PRECIOUS: work/design_%.v work/design_%.bit work/%.stamp
26 changes: 23 additions & 3 deletions timing/util/extract_cell_timings.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def unescape_sdf_name(name):

subtracts = {}

def rewrite_path(modules, modtype, from_pin, to_pin):
def rewrite_path(modules, modtype, from_pin, to_pin, cellconf=None):
# Rewrite a (celltype, from_pin, to_pin) tuple given cell data, or returns None to drop the path
# This looks at the JSON output by Yosys from the Lattice structural Verilog netlist in order
# to determine what the cells in the SDF file are actually doing
Expand Down Expand Up @@ -233,7 +233,17 @@ def strip_prefix_ebr(x, p):
continue
return (ebr_type, strip_prefix_ebr(from_pin, ebr_prefixes), strip_prefix_ebr(to_pin, ebr_prefixes))
if celltype.startswith("LRAM_CORE"):
return ("LRAM_CORE", strip_prefix(from_pin, lram_prefixes), strip_prefix(to_pin, lram_prefixes))
conf_str = ""
if cellconf is not None:
spen = "ENABLE" if cellconf["type"] == "SP512K" else "DISABLE"
if "OUTREG" in cellconf["params"]:
oreg_a = cellconf["params"]["OUTREG"]
oreg_b = cellconf["params"]["OUTREG"]
else:
oreg_a = cellconf["params"]["OUTREG_A"]
oreg_b = cellconf["params"]["OUTREG_B"]
conf_str = ":{},{},{}".format(spen, oreg_a, oreg_b)
return ("LRAM_CORE" + conf_str, strip_prefix(from_pin, lram_prefixes), strip_prefix(to_pin, lram_prefixes))
return None

def main():
Expand All @@ -256,13 +266,23 @@ def main():
with open(sdffile, "rb") as sdff:
sdf = pickle.load(sdff)

# Load cell configuration if any
conffile = netlist.rsplit("_", maxsplit=1)[0] + ".json"
try:
with open(conffile, "r") as fp:
conf = json.load(fp)
except FileNotFoundError:
conf = dict()

speed = sdffile.replace(".sdf.pickle", "").split("_")[-1]
assert speed in speedgrades
for cell in sdf.cells.values():
celltype = unescape_sdf_name(cell.type)
if conf is not None:
cellconf = conf.get(cell.inst.split("\\",maxsplit=1)[0], None)
for entry in cell.entries:
if isinstance(entry, IOPath):
rewritten = rewrite_path(modules, celltype, entry.from_pin, entry.to_pin)
rewritten = rewrite_path(modules, celltype, entry.from_pin, entry.to_pin, cellconf)
if rewritten is None:
continue
if rewritten in iopaths[speed]:
Expand Down