Skip to content

Commit

Permalink
FABulous: Add main() and some cosmetic changes
Browse files Browse the repository at this point in the history
Add main() function.

Reorder includes and remove unused includes.

Fix some docstrings.

Some more cosmetics.

Signed-off-by: Jonas K. <[email protected]>
  • Loading branch information
EverythingElseWasAlreadyTaken committed Sep 7, 2023
1 parent cbe562b commit 140b17a
Showing 1 changed file with 88 additions and 57 deletions.
145 changes: 88 additions & 57 deletions FABulous/FABulous.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,41 @@
#
# SPDX-License-Identifier: Apache-2.0

from contextlib import redirect_stdout
from fabric_generator.model_generation_vpr import genVPRModel
from fabric_generator.utilities import genFabricObject, GetFabric
import fabric_generator.model_generation_vpr as model_gen_vpr
import fabric_generator.model_generation_npnr as model_gen_npnr
from fabric_generator.code_generation_VHDL import VHDLWriter
from fabric_generator.code_generation_Verilog import VerilogWriter
import fabric_generator.code_generator as codeGen
import fabric_generator.file_parser as fileParser
from fabric_generator.fabric import Fabric, Tile
from fabric_generator.fabric_gen import FabricGenerator
import argparse
import cmd
import csv
from glob import glob
import logging
import os
import argparse
import pickle
import re
import sys
import subprocess as sp
import readline
import shutil
import subprocess as sp
import sys
import tkinter as tk
from contextlib import redirect_stdout
from glob import glob
from typing import List, Literal

import docker
import cmd
import readline
import logging
import tkinter as tk
import fabric_generator.code_generator as codeGen
import fabric_generator.file_parser as fileParser
import fabric_generator.model_generation_npnr as model_gen_npnr
import fabric_generator.model_generation_vpr as model_gen_vpr
from fabric_generator.code_generation_Verilog import VerilogWriter
from fabric_generator.code_generation_VHDL import VHDLWriter
from fabric_generator.fabric import Fabric
from fabric_generator.fabric_gen import FabricGenerator
from fabric_generator.utilities import GetFabric, genFabricObject

readline.set_completer_delims(' \t\n')

logger = logging.getLogger(__name__)
logging.basicConfig(
format="[%(levelname)s]-%(asctime)s - %(message)s", level=logging.INFO)

metaDataDir = ".FABulous"

fabulousRoot = os.getenv('FAB_ROOT')
if fabulousRoot is None:
fabulousRoot = os.path.dirname(os.path.realpath(__file__))
Expand Down Expand Up @@ -263,20 +265,20 @@ def _complete_tileName(self, text):
return [t for t in self.allTile if t.startswith(text)]

def do_shell(self, args):
"Run a shell command"
"""Run a shell command."""
if not args:
print("Please provide a command to run")
return

sp.run(args, shell=True)

def do_exit(self, *ignore):
"exit FABulous shell"
"""Exit FABulous shell."""
logger.info("Exiting FABulous shell")
return True

def do_load_fabric(self, args=""):
"load csv file and generate an internal representation of the fabric"
"""Load csv file and generate an internal representation of the fabric."""
args = self.parse(args)
# if no argument is given will use the one set by set_fabric_csv
# else use the argument
Expand Down Expand Up @@ -312,15 +314,15 @@ def complete_load_fabric(self, text, *ignored):

# TODO REMOVE once have transition the model gen to object based
def do_set_fabric_csv(self, args):
"set the csv file to be used for fabric generation"
"""Set the csv file to be used for fabric generation."""
args = self.parse(args)
self.csvFile = args[0]

def complete_set_fabric_csv(self, text, *ignored):
return self._complete_path(text)

def do_gen_config_mem(self, args):
"Generate the configuration memory of the given tile"
"""Generate the configuration memory of the given tile."""
args = self.parse(args)
logger.info(f"Generating Config Memory for {' '.join(args)}")
for i in args:
Expand All @@ -329,13 +331,13 @@ def do_gen_config_mem(self, args):
f"{self.projectDir}/Tile/{i}/{i}_ConfigMem.{self.extension}")
self.fabricGen.genConfigMem(
i, f"{self.projectDir}/Tile/{i}/{i}_ConfigMem.csv")
logger.info(f"Generating configMem complete")
logger.info("Generating configMem complete")

def complete_gen_config_mem(self, text, *ignored):
return self._complete_tileName(text)

def do_gen_switch_matrix(self, args):
"Generate switch matrix of the given tile"
"""Generate switch matrix of the given tile."""
args = self.parse(args)
logger.info(f"Generating switch matrix for {' '.join(args)}")
for i in args:
Expand All @@ -349,7 +351,7 @@ def complete_gen_switch_matrix(self, text, *ignored):
return self._complete_tileName(text)

def do_gen_tile(self, args):
"Generate the given tile with the switch matrix and configuration memory"
"""Generate the given tile with the switch matrix and configuration memory."""
if not isinstance(args, list):
args = self.parse(args)
logger.info(f"Generating tile {' '.join(args)}")
Expand Down Expand Up @@ -410,13 +412,13 @@ def complete_gen_tile(self, text: str, *ignored):
return self._complete_tileName(text)

def do_gen_all_tile(self, *ignored):
"Generate all tiles"
"""Generate all tiles."""
logger.info("Generating all tiles")
self.do_gen_tile(self.allTile)
logger.info("Generated all tiles")

def do_gen_fabric(self, *ignored):
"Generate the fabric base on the loaded fabric"
"""Generate the fabric base on the loaded fabric."""
logger.info(f"Generating fabric {self.fabricGen.fabric.name}")
self.do_gen_all_tile()
self.fabricGen.setWriterOutputFile(
Expand All @@ -425,7 +427,7 @@ def do_gen_fabric(self, *ignored):
logger.info("Fabric generation complete")

def do_gen_bitStream_spec(self, *ignored):
"Generate the bitstream specification of the fabric"
"""Generate the bitstream specification of the fabric."""
logger.info("Generating bitstream specification")
specObject = self.fabricGen.genBitStreamSpec()

Expand All @@ -445,15 +447,19 @@ def do_gen_bitStream_spec(self, *ignored):
logger.info("Generated bitstream specification")

def do_gen_top_wrapper(self, *ignored):
"Generate the top wrapper of the fabric"
"""Generate the top wrapper of the fabric."""
logger.info("Generating top wrapper")
self.fabricGen.setWriterOutputFile(
f"{self.projectDir}/Fabric/{self.fabricGen.fabric.name}_top.{self.extension}")
self.fabricGen.genTopWrapper()
logger.info("Generated top wrapper")

def do_run_FABulous_fabric(self, *ignored):
"Generate the fabric base on the CSV file, create the bitstream specification of the fabric, top wrapper of the fabric and Nextpnr model of the fabric"
"""
Generate the fabric base on the CSV file, create the bitstream
specification of the fabric, top wrapper of the fabric and Nextpnr model
of the fabric.
"""
logger.info("Running FABulous")
self.do_gen_fabric()
self.do_gen_bitStream_spec()
Expand All @@ -463,7 +469,7 @@ def do_run_FABulous_fabric(self, *ignored):
return 0

def do_gen_model_npnr(self, *ignored):
"Generate a npnr model of the fabric"
"""Generate a npnr model of the fabric."""
logger.info("Generating npnr model")
npnrModel = self.fabricGen.genModelNpnr()
logger.info(
Expand All @@ -489,7 +495,10 @@ def do_gen_model_npnr(self, *ignored):

# TODO updater once have transition the model gen to object based
def do_gen_model_npnr_pair(self):
"Generate a pair npnr model of the fabric. (Currently not working)"
"""
Generate a pair npnr model of the fabric.
(Currently not working).
"""
logger.info("Generating pair npnr model")
if self.csvFile:
FabricFile = [i.strip('\n').split(',') for i in open(self.csvFile)]
Expand Down Expand Up @@ -519,10 +528,10 @@ def do_gen_model_npnr_pair(self):
logger.info("Generated pair npnr model")

def do_gen_model_vpr(self, args):
"Generate a vpr model of the fabric"
"""Generate a vpr model of the fabric."""
args = self.parse(args)
if len(args) > 1:
logger.error(f"Usage: gen_model_vpr [path_to_custom_xml]")
logger.error("Usage: gen_model_vpr [path_to_custom_xml]")
return

if len(args) == 0:
Expand Down Expand Up @@ -564,11 +573,11 @@ def complete_gen_model_vpr(self, text, *ignored):
return self._complete_path(text)

def do_hls_create_project(self):
if not os.path.exists(f"./HLS"):
os.makedirs(f"./HLS")
if not os.path.exists("./HLS"):
os.makedirs("./HLS")

with open(f"{self.projectDir}/HLS/config.tcl", "w") as f:
f.write(f"source /root/legup-4.0/examples/legup.tcl\n")
f.write("source /root/legup-4.0/examples/legup.tcl\n")

name = self.projectDir.split('/')[-1]
with open(f"{self.projectDir}/HLS/Makefile", "w") as f:
Expand All @@ -584,18 +593,17 @@ def do_hls_create_project(self):
f.write(
'#include <stdio.h>\nint main() {\n printf("Hello World");\n return 0;\n}')

os.chmod(f"./HLS/config.tcl", 0o666)
os.chmod(f"./HLS/Makefile", 0o666)
os.chmod("./HLS/config.tcl", 0o666)
os.chmod("./HLS/Makefile", 0o666)
os.chmod(f"./HLS/{name}.c", 0o666)

def do_hls_generate_verilog(self):
name = self.projectDir.split('/')[-1]
# create folder for the generated file
if not os.path.exists(f"./HLS/generated_file"):
if not os.path.exists("./HLS/generated_file"):
os.mkdir(f"{name}/generated_file")
else:
os.system(
f"rm -rf ./create_HLS_project/generated_file/*")
os.system("rm -rf ./create_HLS_project/generated_file/*")

client = docker.from_env()
containers = client.containers.run(
Expand All @@ -604,15 +612,15 @@ def do_hls_generate_verilog(self):
print(containers.decode("utf-8"))

# move all the generated files into a folder
for f in os.listdir(f"./HLS"):
for f in os.listdir("./HLS"):
if not f.endswith(".v") and not f.endswith(".c") and not f.endswith(".h") and not f.endswith("_labeled.c") \
and not f.endswith(".tcl") and f != "Makefile" and os.path.isfile(f"./HLS/{f}"):
shutil.move(f"./HLS/{f}",
f"./HLS/generated_file/")
"./HLS/generated_file/")

if f.endswith("_labeled.c"):
shutil.move(f"./HLS/{f}",
f"./HLS/generated_file/")
"./HLS/generated_file/")

try:
os.chmod(f"./HLS/{name}.v", 0o666)
Expand Down Expand Up @@ -656,7 +664,10 @@ def do_hls_generate_verilog(self):
exit(-1)

def do_synthesis_npnr(self, args):
"Run synthesis with Yosys using Nextpnr JSON backend Usage: synthesis_npnr <dir_to_top_module>"
"""
Run synthesis with Yosys using Nextpnr JSON backend.
Usage: synthesis_npnr <dir_to_top_module>
"""
args = self.parse(args)
if len(args) != 1:
logger.error("Usage: synthesis_npnr <dir_to_top_module>")
Expand All @@ -676,7 +687,10 @@ def complete_synthesis_npnr(self, text, *ignored):
return self._complete_path(text)

def do_synthesis_blif(self, args):
"Run synthesis with Yosys using VPR BLIF backend Usage: synthesis_blif <dir_to_top_module>"
"""
Run synthesis with Yosys using VPR BLIF backend.
Usage: synthesis_blif <dir_to_top_module>
"""
args = self.parse(args)
if len(args) != 1:
logger.error("Usage: synthesis_blif <dir_to_top_module>")
Expand All @@ -696,7 +710,10 @@ def complete_synthesis_blif(self, text, *ignored):
return self._complete_path(text)

def do_place_and_route_npnr(self, args):
"Run place and route with Nextpnr. Need to generate a Nextpnr model first. Usage: place_and_route_npnr <dir_to_top_module>"
"""
Run place and route with Nextpnr. Need to generate a Nextpnr model first.
Usage: place_and_route_npnr <dir_to_top_module>
"""
args = self.parse(args)
if len(args) != 1:
logger.error("Usage: place_and_route_npnr <dir_to_top_module>")
Expand Down Expand Up @@ -734,7 +751,10 @@ def complete_place_and_route_npnr(self, text, *ignored):
return self._complete_path(text)

def do_place_and_route_vpr(self, args):
"Run place and route with VPR. Need to generate a VPR model first. Usage: place_and_route_vpr <dir_to_top_module> (Currently not working)"
"""
Run place and route with VPR. Need to generate a VPR model first.
Usage: place_and_route_vpr <dir_to_top_module> (Currently not working)
"""
args = self.parse(args)
if len(args) != 1:
logger.error("Usage: place_and_route_vpr <dir_to_top_module>")
Expand All @@ -753,9 +773,9 @@ def do_place_and_route_vpr(self, args):
vtr_root = os.getenv('VTR_ROOT')

runCmd = [f"{vtr_root}/vpr/vpr",
f".FABulous/architecture.xml",
".FABulous/architecture.xml",
f"{self.projectDir}/user_design/{name}.blif",
"--read_rr_graph", f".FABulous/routing_resources.xml",
"--read_rr_graph", ".FABulous/routing_resources.xml",
"--echo_file", "on",
"--route_chan_width", "16"]
sp.run(runCmd, check=True)
Expand All @@ -769,7 +789,10 @@ def complete_place_and_route_vpr(self, text, *ignored):
return self._complete_path(text)

def do_gen_bitStream_binary(self, args):
"Generate the bitstream of a given design. Need to generate bitstream specification before use. Usage: gen_bitStream_binary <dir_to_top_module>"
"""
Generate the bitstream of a given design. Need to generate bitstream
specification before use. Usage: gen_bitStream_binary <dir_to_top_module>
"""
args = self.parse(args)
if len(args) != 1:
logger.error("Usage: gen_bitStream_binary <dir_to_top_module>")
Expand Down Expand Up @@ -803,7 +826,11 @@ def complete_gen_bitStream_binary(self, text, *ignored):
return self._complete_path(text)

def do_run_FABulous_bitstream(self, *args):
"Run FABulous to generate a bitstream on a given design starting from synthesis. Usage: run_FABulous_bitstream <npnr|vpr> <dir_to_top_module> (vpr flow currently not working)"
"""
Run FABulous to generate a bitstream on a given design starting from
synthesis. Usage: run_FABulous_bitstream <npnr|vpr> <dir_to_top_module>
(vpr flow currently not working)
"""
if len(args) == 1:
args = self.parse(args[0])
if len(args) != 2:
Expand Down Expand Up @@ -858,7 +885,7 @@ def complete_tcl(self, text, *ignored):
return self._complete_path(text)


if __name__ == "__main__":
def main():
if sys.version_info < (3, 9, 0):
print("Need Python 3.9 or above to run FABulous")
exit(-1)
Expand Down Expand Up @@ -901,7 +928,7 @@ def complete_tcl(self, text, *ignored):
args = parser.parse_args()

args.top = args.project_dir.split("/")[-1]
metaDataDir = ".FABulous"


if args.createProject:
create_project(args.project_dir, args.writer)
Expand Down Expand Up @@ -929,3 +956,7 @@ def complete_tcl(self, text, *ignored):
fabShell.cmdloop()
else:
fabShell.cmdloop()


if __name__ == "__main__":
main()

0 comments on commit 140b17a

Please sign in to comment.