Routing nchor added
This commit is contained in:
+93
-27
@@ -122,6 +122,36 @@ def cell_svg_path(project_name, cell_name):
|
||||
return os.path.join(project_root(project_name), f"{safe_name(cell_name, 'canvas_1')}.svg")
|
||||
|
||||
|
||||
def cell_routes_path(project_name, cell_name):
|
||||
return os.path.join(project_root(project_name), f"{safe_name(cell_name, 'canvas_1')}.routes.yml")
|
||||
|
||||
|
||||
def write_route_points_sidecar(yaml_content, output_path):
|
||||
layout = yaml.safe_load(yaml_content) or {}
|
||||
routes = {}
|
||||
for bundle_name, bundle in (layout.get("bundles") or {}).items():
|
||||
saved_links = []
|
||||
for link in bundle.get("links") or []:
|
||||
points = link.get("points") or []
|
||||
if not points:
|
||||
continue
|
||||
saved_links.append({
|
||||
"from": link.get("from"),
|
||||
"to": link.get("to"),
|
||||
"xsection": link.get("xsection"),
|
||||
"width": link.get("width"),
|
||||
"radius": link.get("radius"),
|
||||
"points": points,
|
||||
})
|
||||
if saved_links:
|
||||
routes[bundle_name] = {"links": saved_links}
|
||||
if routes:
|
||||
with open(output_path, 'w', encoding='utf-8') as file:
|
||||
yaml.safe_dump({"routes": routes}, file, sort_keys=False)
|
||||
elif os.path.exists(output_path):
|
||||
os.remove(output_path)
|
||||
|
||||
|
||||
def project_gds_path(project_name):
|
||||
return os.path.join(project_root(project_name), f"{safe_name(project_name, 'project_1')}.gds")
|
||||
|
||||
@@ -145,6 +175,28 @@ def current_pdk_registry():
|
||||
return PdkRegistry(current_pdk_root(), prefer_full_gds=prefer_full_gds_for_session(session))
|
||||
|
||||
|
||||
def scoped_pdk_root_for_project(project_name):
|
||||
base_root = current_pdk_root()
|
||||
project = safe_name(project_name, '')
|
||||
if not project:
|
||||
return base_root
|
||||
|
||||
technology_id = read_project_meta(project).get("technology") or ""
|
||||
if "/" not in technology_id:
|
||||
return base_root
|
||||
|
||||
foundry, technology = technology_id.split("/", 1)
|
||||
scoped_root = os.path.abspath(os.path.join(base_root, foundry, technology))
|
||||
if scoped_root == base_root or not scoped_root.startswith(base_root + os.sep):
|
||||
return base_root
|
||||
return scoped_root if os.path.isdir(scoped_root) else base_root
|
||||
|
||||
|
||||
def pdk_root_for_request_project():
|
||||
project = request.args.get('project')
|
||||
return scoped_pdk_root_for_project(project) if project else current_pdk_root()
|
||||
|
||||
|
||||
def project_meta_path(project_name):
|
||||
return os.path.join(project_root(project_name), ".project.json")
|
||||
|
||||
@@ -172,10 +224,11 @@ def ensure_project_path(project_name):
|
||||
|
||||
# ... [Keep countSpaces and buildTree exactly as they are] ...
|
||||
|
||||
def findComps(baseDir):
|
||||
def findComps(baseDir, path_root=None):
|
||||
"""Scan component folders, return map of paths -> component info."""
|
||||
compMap = {}
|
||||
refDir = baseDir
|
||||
path_root = os.path.abspath(path_root or baseDir)
|
||||
for root, dirs, files in os.walk(baseDir):
|
||||
ymlFiles = [f for f in files if f.endswith('.yml')]
|
||||
if ymlFiles:
|
||||
@@ -191,7 +244,8 @@ def findComps(baseDir):
|
||||
compMap[parts + (compName,)] = {
|
||||
'folder': compName,
|
||||
'yml': ymlFiles[0],
|
||||
'category': category # Save the category to the map
|
||||
'category': category, # Save the category to the map
|
||||
'path': os.path.relpath(root, path_root).replace(os.sep, '/')
|
||||
}
|
||||
dirs.clear()
|
||||
return compMap
|
||||
@@ -214,7 +268,8 @@ def addCompsToTree(compMap):
|
||||
"__type__": "component",
|
||||
"__name__": compName,
|
||||
"__yml__": compItem['yml'],
|
||||
"__category__": compItem['category'] # Inject category into the tree
|
||||
"__category__": compItem['category'], # Inject category into the tree
|
||||
"__path__": compItem.get('path')
|
||||
})
|
||||
|
||||
return fresh_tree
|
||||
@@ -258,6 +313,15 @@ def readCompYaml(compName, comps_root=None):
|
||||
return yaml.safe_load(f)
|
||||
return None
|
||||
|
||||
|
||||
def find_component_dir(component_name, comps_root=None):
|
||||
search_root = comps_root or current_pdk_root()
|
||||
for root, dirs, files in os.walk(search_root):
|
||||
if os.path.basename(root) == component_name:
|
||||
dirs.clear()
|
||||
return root, files
|
||||
return None, []
|
||||
|
||||
# --- AUTHENTICATION & PAGE ROUTES ---
|
||||
@app.route('/')
|
||||
def home():
|
||||
@@ -588,25 +652,29 @@ def save_layout():
|
||||
project = safe_name(data.get('project'), 'project_1')
|
||||
cell = safe_name(data.get('cell'), 'canvas_1')
|
||||
content = data.get('content', '')
|
||||
create_preview = bool(data.get('preview', True))
|
||||
|
||||
save_path = cell_file_path(project, cell)
|
||||
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
||||
|
||||
with open(save_path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
write_route_points_sidecar(content, cell_routes_path(project, cell))
|
||||
|
||||
svg_path = cell_svg_path(project, cell)
|
||||
if layout_has_links(content):
|
||||
create_routed_layout_svg(
|
||||
content,
|
||||
svg_path,
|
||||
pdk_root=current_pdk_root(),
|
||||
project_dir=project_root(project),
|
||||
technology_manifest_path=technology_manifest_path_for_project(project),
|
||||
prefer_full_gds=prefer_full_gds_for_session(session),
|
||||
)
|
||||
else:
|
||||
create_layout_svg_from_gds(content, svg_path, pdk_registry=current_pdk_registry(), project_dir=project_root(project))
|
||||
svg_path = None
|
||||
if create_preview:
|
||||
svg_path = cell_svg_path(project, cell)
|
||||
if layout_has_links(content):
|
||||
create_routed_layout_svg(
|
||||
content,
|
||||
svg_path,
|
||||
pdk_root=current_pdk_root(),
|
||||
project_dir=project_root(project),
|
||||
technology_manifest_path=technology_manifest_path_for_project(project),
|
||||
prefer_full_gds=prefer_full_gds_for_session(session),
|
||||
)
|
||||
else:
|
||||
create_layout_svg_from_gds(content, svg_path, pdk_registry=current_pdk_registry(), project_dir=project_root(project))
|
||||
|
||||
record_action('layout.save', project=project, cell=cell, detail={"bytes": len(content), "svg": svg_path})
|
||||
return jsonify({
|
||||
@@ -615,7 +683,7 @@ def save_layout():
|
||||
"cell": cell,
|
||||
"path": save_path,
|
||||
"svg_path": svg_path,
|
||||
"svg_url": url_for('get_layout_svg', project_name=project, cell_name=cell)
|
||||
"svg_url": url_for('get_layout_svg', project_name=project, cell_name=cell) if svg_path else None
|
||||
}), 200
|
||||
|
||||
except Exception as e:
|
||||
@@ -716,10 +784,10 @@ def get_project_gds(project_name, filename):
|
||||
@login_required_json
|
||||
def getLib():
|
||||
"""Get library structure."""
|
||||
comps_root = current_pdk_root()
|
||||
comps_root = pdk_root_for_request_project()
|
||||
fresh_tree = {}
|
||||
if os.path.isdir(comps_root):
|
||||
compMap = findComps(comps_root)
|
||||
compMap = findComps(comps_root, current_pdk_root())
|
||||
fresh_tree = addCompsToTree(compMap)
|
||||
return jsonify(fresh_tree)
|
||||
|
||||
@@ -729,7 +797,7 @@ def getLib():
|
||||
@login_required_json
|
||||
def getComp(component_name):
|
||||
"""Return component YAML data."""
|
||||
data = readCompYaml(component_name, current_pdk_root())
|
||||
data = readCompYaml(component_name, pdk_root_for_request_project())
|
||||
if data is None:
|
||||
return jsonify({"error": "Component not found"}), 404
|
||||
return jsonify(data)
|
||||
@@ -738,14 +806,12 @@ def getComp(component_name):
|
||||
@login_required_json
|
||||
def getCompImg(component_name):
|
||||
"""Return first image in component folder."""
|
||||
for root, dirs, files in os.walk(current_pdk_root()):
|
||||
if os.path.basename(root) == component_name:
|
||||
dirs.clear()
|
||||
for ext in ('.png', '.jpg', '.jpeg', '.svg'):
|
||||
for f in files:
|
||||
if f.lower().endswith(ext):
|
||||
return send_from_directory(root, f)
|
||||
break
|
||||
root, files = find_component_dir(component_name, pdk_root_for_request_project())
|
||||
if root:
|
||||
for ext in ('.png', '.jpg', '.jpeg', '.svg'):
|
||||
for f in files:
|
||||
if f.lower().endswith(ext):
|
||||
return send_from_directory(root, f)
|
||||
return jsonify({"error": "No image found"}), 404
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user