Skip to content
Draft
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
1 change: 1 addition & 0 deletions conf/requirements-symbiflow.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ sympy
textx
python-constraint
fasm
matplotlib
git+https://github.com/SymbiFlow/prjxray.git@e25c20a8f158cc5e94eb62e3b74e16fc9d6c1d26#egg=prjxray
git+https://github.com/symbiflow/xc-fasm.git@14afc2bae24cbf6ee5e7d057a58b4cbd776358d0#egg=xc-fasm
1 change: 1 addition & 0 deletions conf/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ meson
Pillow
six
Wave
matplotlib
121 changes: 121 additions & 0 deletions scripts/critpath.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env python3
# Copyright 2022 The CFU-Playground Authors
#
# 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.
#
#
# Display color-coded floowplan and critical path,
# using data files written by nextpnr.
# Currently the critical path display is disabled
# since it hasn't been tested with ice40.
#



import json
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import random

fig, ax = plt.subplots(dpi=200)

# read placement file
with open('placement_data.txt', 'r') as pfile:
placement_data=pfile.readlines()

if True:
# read critical path file
with open('kosagi_fomu_pvt-report.json', 'r') as myfile:
data=myfile.read()

# parse file
obj = json.loads(data)

# assume first CP is the one we're interested in (maybe print out from/to clk domains)
cp = obj['critical_paths'][0]['path']
#print(cp)

accum = {}
accum['logic'] = 0.0
accum['routing'] = 0.0
accum['clk-to-q'] = 0.0
accum['setup'] = 0.0

# plot placement data first
for line in placement_data:
if 'KEY' in line:
continue
[type,x,y,color]=line.rstrip().split(' ')
x = int(x)
y = int(y)
if type == 'small':
rx = random.uniform(0,0.7)
ry = random.uniform(0,0.7)
ax.add_patch(mpatches.Rectangle(
[x+rx, y+ry], 0.1, 0.1,
color=color, fill=True))
if type == 'med':
ax.add_patch(mpatches.Rectangle(
[x, y-0.2], 1.6, 1.6,
color=color, ec='white', fill=True))
if type == 'circle':
ax.add_patch(mpatches.Circle(
[x, y+0.5], 0.7,
color=color, ec='white', fill=True))

ax.set_aspect('equal')
ax.autoscale_view()


if 'cp' in locals():
xs = []
ys = []
for hop in cp:
dtype = hop['type']
accum[dtype] += hop['delay']
fromcell = hop['from']['cell']
tocell = hop['to']['cell']
delay = "%.3f" % hop['delay']
fromloc = hop['from']['loc']
toloc = hop['to']['loc']
floc = str(fromloc[0]) + ":" + str(fromloc[1])
tloc = str(toloc[0]) + ":" + str(toloc[1])
if toloc != fromloc:
xs.append(fromloc[0])
ys.append(fromloc[1])
xs.append(toloc[0])
ys.append(toloc[1])
if 'clk' in dtype:
print(f"from {tloc} {tocell} {dtype} --> {delay} ->")
else:
print(f"from {floc} {fromcell} {dtype} --> {delay} ->")

plt.plot(xs, ys, marker='x', linewidth=3, color='black', label=delay)

print("");
for k,v in accum.items():
delay = "%.2f" % v
print(f"total {k}: {delay}")

print("");
for line in placement_data:
if 'KEY' in line:
print(line.rstrip())
print("KEY Multiplier Circle")
print("KEY Memory Square")

plt.xlim([0, 27])
plt.ylim([0, 32])
# plt.show()
plt.savefig("critpath.png", format="png", dpi=300)
print("Done writing critical path image.\n")
67 changes: 67 additions & 0 deletions scripts/save-placement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/env python3
# Copyright 2022 The CFU-Playground Authors
#
# 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.
#
# When executed by nextpnr-ice40 using the "--pre-route" option,
# this saves placement data in a file "placement_data.txt".


import sys

print("\nSaving placement data...\n")

COLOR_TABLE = [
('Vex', 'gray'),
('Cfu', 'seagreen'),
('litespi', 'blue'),
('cdcusbphy', 'red'),
('_usb_', 'red'),
]

with open('placement_data.txt', 'w') as f:
for cell, cellinfo in ctx.cells:
if cellinfo.bel:
bel = cellinfo.bel
#print(cell, file=f)
#print(bel, file=f)
loc = ctx.getBelLocation(bel)
x = int(loc.x)
y = int(loc.y)

color = 'black'
for match, c in COLOR_TABLE:
if match in cell:
color = c

mul = "DSP" in cell
ebr = "/ram" in bel

# Set color for LRAMs
lram = "spram_" in bel
color= 'tan' if lram else color

if mul:
print(f"circle {x} {y} {color}", file=f)
elif ebr or lram:
print(f"med {x} {y} {color}", file=f)
else:
print(f"small {x} {y} {color}", file=f)

for i, (match, c) in enumerate(COLOR_TABLE):
print(f"KEY {match} {c}", file=f)
print("KEY LiteX black", file=f)

print("\nDone\n")

# sys.exit()
14 changes: 14 additions & 0 deletions soc/board_specific_workflows/ice40up5k.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@
from typing import Callable


_ice40_placement_build_template = [
"yosys -l {build_name}.rpt {build_name}.ys",
"nextpnr-ice40 --json {build_name}.json --pcf {build_name}.pcf --asc {build_name}.txt \
--pre-route ../../../../scripts/save-placement.py \
--report={build_name}-report.json \
--pre-pack {build_name}_pre_pack.py --{architecture} --package {package} {timefailarg} {ignoreloops} --seed {seed}",
"icepack -s {build_name}.txt {build_name}.bin",
"critpath.py > critpath.log"
]


class Ice40UP5KWorkflow(general.GeneralSoCWorkflow):
"""Workflow for boards derived from the Ice40UP5K.
Expand Down Expand Up @@ -64,6 +74,10 @@ def make_soc(self, **kwargs) -> litex_soc.LiteXSoC:
soc.bus.regions["sram"].size = 128 * 1024;
soc.bus.regions["main_ram"].origin = 128 * 1024;
soc.bus.regions["main_ram"].size = 0;

# add scripts for plotting placement
soc.platform.toolchain.build_template = _ice40_placement_build_template

return soc

def software_load(
Expand Down