Use new file emission trait + makefile naming cleanup

This commit is contained in:
David Biancolin 2021-07-02 23:13:38 +00:00
parent fa8b1a98f8
commit 2e30100d35
25 changed files with 302 additions and 237 deletions

View File

@ -42,7 +42,7 @@ def replace_rtl(conf, buildconfig):
InfoStreamLogger('stderr'):
run(buildconfig.make_recipe("replace-rtl"))
run("""mkdir -p {}/results-build/{}/""".format(ddir, builddir))
run("""cp $CL_DIR/design/cl_firesim_generated.sv {}/results-build/{}/cl_firesim_generated.sv""".format(ddir, builddir))
run("""cp $CL_DIR/design/FireSim-generated.sv {}/results-build/{}/FireSim-generated.sv""".format(ddir, builddir))
# build the fpga driver that corresponds with this version of the RTL
with prefix('cd ' + ddir + '/../'), \

View File

@ -1,3 +1,5 @@
.. _auto-ila:
AutoILA: Simple Integrated Logic Analyzer (ILA) Insertion
===================================================================

View File

@ -0,0 +1,30 @@
Output Files
============
Golden Gate generates many output files, we describe them here. Note, the GG
CML-argument ``--output-filename-base=<BASE>`` defines defines a common prefix
for all output files.
Core Files
-------------------------------------
These are used in nearly all flows.
* **<BASE>.v**: The verilog implementation of the simulator which will be synthesized onto the FPGA. The top-level is the Shim module specified in the ``PLATFORM_CONFIG``.
* **<BASE>_const.h**: A target-specific header containing all necessary metadata to instantiate bridge drivers. This is linked into the simulator driver and meta-simulators (FPGA-level / MIDAS-level). Often referred to as "the header".
* **<BASE>_runtime.conf**: Default plus args for generated FASED memory timing models. Most other bridges have their defaults baked into the driver.
FPGA Synthesis Files
-------------------------------------
These are additional files passed to the FPGA build directory.
* **<BASE>_defines.vh**: Verilog macro definitions for FPGA synthesis.
* **<BASE>_env.tcl**: Used a means to inject arbitrary TCL into the start of the build flow. Controls synthesis and implementation strategies, and sets the host_clock frequency before the clock generator (MCMM) is synthesized.
* **<BASE>_ila_insert_vivado.tcl**: Synthesizes an ILA for the design. See :ref:`auto-ila` for more details about using ILAs in FireSim.
* **<BASE>_ila_insert_{inst, ports, wires}.v**: Instantiated in the FPGA project via ```include`` directives to instantiate the generated ILA.
Meta-simulation Files
-------------------------------------
These are additional sources used only in MIDAS-level simulators
* **<BASE>_const.vh**: Verilog macros to define variable width fields.

View File

@ -33,7 +33,7 @@ New to FireSim? Jump to the :ref:`firesim-basics` page for more info.
.. toctree::
:maxdepth: 3
:caption: Golden Gate (MIDAS II) Docs:
:caption: Compiler (Golden Gate) Docs:
Golden-Gate/Overview
Golden-Gate/LI-BDN
@ -41,6 +41,7 @@ New to FireSim? Jump to the :ref:`firesim-basics` page for more info.
Golden-Gate/Bridge-Walkthrough
Golden-Gate/Triggers
Golden-Gate/Resource-Optimizations
Golden-Gate/Output-Files
Indices and tables
==================

@ -1 +1 @@
Subproject commit cb2cc9b1b146c0302bf5b74993dfd45de1569f9a
Subproject commit e0745fae2d8c92054b4defcf76ce81f166635612

View File

@ -6,19 +6,20 @@ endif
firesim_base_dir := $(abspath .)
.PHONY: default
default: compile
##################
# Parameters #
##################
# Multiple target-projects, each with it's own chisel generator, co-exist in firesim.
# Multiple target-projects, each with their own chisel generator, co-exist in firesim.
# Their sources exist in:
# src/main/{cc, scala, makefrag}/<target-project-name>
#
# Currently these projects are:
# firesim: the default, rocket-chip-based target-designs
# midasexamples: simple chisel designs demonstrating how to build midas-style simulators
# firesim: the default, Chipyard-based target-designs
# midasexamples: simple chisel designs demonstrating FireSim's features
TARGET_PROJECT ?= firesim
# Users can override this to point at a makefrag defined in a parent project
@ -92,8 +93,6 @@ endif
# Include target-specific sources and input generation recipes
include $(TARGET_PROJECT_MAKEFRAG)
verilog: $(VERILOG)
compile: $(VERILOG)
# Phony targets for launching the sbt shell and running scalatests
SBT_COMMAND ?= shell

View File

@ -4,6 +4,7 @@ package firesim.passes
import firesim.util.{DesiredHostFrequency, BuildStrategy}
import midas.stage.phases.ConfigParametersAnnotation
import midas.stage.GoldenGateOutputFileAnnotation
import freechips.rocketchip.config.Parameters
@ -19,40 +20,28 @@ import java.io.{File, FileWriter}
object EC2F1Artefacts extends Transform {
def inputForm: CircuitForm = LowForm
def outputForm: CircuitForm = LowForm
override def name = "[FireSim] EC2 F1 Artefact Generation"
def writeOutputFile(f: File, contents: String): File = {
val fw = new FileWriter(f)
fw.write(contents)
fw.close
f
}
override def name = "[Golden Gate] EC2 F1 Artefact Generation"
// Capture FPGA-toolflow related verilog defines
def generateHostVerilogHeader(targetDir: File) {
val headerName = "cl_firesim_generated_defines.vh"
writeOutputFile(new File(targetDir, headerName), s"\n")
}
def verilogHeaderAnno = GoldenGateOutputFileAnnotation(
"""| // Don't let Vivado see $random, which is the default if this is not set
| `define RANDOM 64'b0
|""".stripMargin,
fileSuffix = ".defines.vh")
// Emit TCL variables to control the FPGA compilation flow
def generateTclEnvFile(targetDir: File)(implicit hostParams: Parameters) {
val headerName = "cl_firesim_generated_env.tcl"
def tclEnvAnno(implicit hostParams: Parameters): GoldenGateOutputFileAnnotation = {
val requestedFrequency = hostParams(DesiredHostFrequency)
val buildStrategy = hostParams(BuildStrategy)
val constraints = s"""# FireSim Generated Environment Variables
set desired_host_frequency ${requestedFrequency}
${buildStrategy.emitTcl}
"""
writeOutputFile(new File(targetDir, headerName), constraints)
GoldenGateOutputFileAnnotation(constraints, fileSuffix = ".env.tcl")
}
def execute(state: CircuitState): CircuitState = {
implicit val p = state.annotations.collectFirst({ case ConfigParametersAnnotation(p) => p }).get
val targetDir = state.annotations.collectFirst({
case TargetDirAnnotation(dir) => new File(dir)
}).get
generateHostVerilogHeader(targetDir)
generateTclEnvFile(targetDir)
state
state.copy(annotations = verilogHeaderAnno +: tclEnvAnno +: state.annotations)
}
}

View File

@ -5,6 +5,7 @@ package firesim.passes
import midas.EnableAutoILA
import midas.targetutils.FirrtlFpgaDebugAnnotation
import midas.stage.{OutputFileBuilder, GoldenGateOutputFileAnnotation}
import midas.stage.phases.ConfigParametersAnnotation
import firrtl._
@ -30,26 +31,23 @@ class ILATopWiringTransform extends Transform with DependencyAPIMigration {
type InstPath = Seq[String]
val addedFileAnnos = new mutable.ArrayBuffer[GoldenGateOutputFileAnnotation]
def ILAWiringOutputFiles(dataDepth: Int)(
dir: String,
mapping: Seq[((ComponentName, Type, Boolean, InstPath, String), Int)],
state: CircuitState): CircuitState = {
//val targetFile: Option[String] = state.annotations.collectFirst { case ILADebugFileAnnotation(fn) => fn }
//output vivado tcl file
val tclOutputFile = new PrintWriter(new File(dir, "firesim_ila_insert_vivado.tcl" ))
//output verilog 'include' file with ports
val portsOutputFile = new PrintWriter(new File(dir, "firesim_ila_insert_ports.v" ))
//output verilog 'include' file with wires
val wiresOutputFile = new PrintWriter(new File(dir, "firesim_ila_insert_wires.v" ))
//output verilog 'include' file with ila instantiation
val ilaInstOutputFile = new PrintWriter(new File(dir, "firesim_ila_insert_inst.v" ))
// vivado >2017.4 encrypt chokes on empty .v files, so put something there...
portsOutputFile.append(s" \n \n \n")
wiresOutputFile.append(s" \n \n \n")
ilaInstOutputFile.append(s" \n \n \n")
def fileHeader = " \n \n \n"
//output vivado tcl file
val tclOutputFile = new OutputFileBuilder(fileHeader, ".ila_insert_vivado.tcl")
//output verilog 'include' file with ports
val portsOutputFile = new OutputFileBuilder(fileHeader, ".ila_insert_ports.v")
//output verilog 'include' file with wires
val wiresOutputFile = new OutputFileBuilder(fileHeader, ".ila_insert_wires.v")
//output verilog 'include' file with ila instantiation
val ilaInstOutputFile = new OutputFileBuilder(fileHeader, ".ila_insert_inst.v")
//vivado tcl prologue
tclOutputFile.append(s"create_project managed_ip_project $$CL_DIR/ip/firesim_ila_ip/managed_ip_project -part xcvu9p-flgb2104-2-i -ip -force\n")
@ -123,11 +121,12 @@ class ILATopWiringTransform extends Transform with DependencyAPIMigration {
ilaInstOutputFile.append(s"\n);\n")
}
tclOutputFile.close()
portsOutputFile.close()
wiresOutputFile.close()
ilaInstOutputFile.close()
addedFileAnnos ++= Seq(
tclOutputFile.toAnnotation,
portsOutputFile.toAnnotation,
wiresOutputFile.toAnnotation,
ilaInstOutputFile.toAnnotation
)
state
}
@ -153,14 +152,16 @@ class ILATopWiringTransform extends Transform with DependencyAPIMigration {
case p => p.map { case FirrtlFpgaDebugAnnotation(target) => TopWiringAnnotation(target, s"ila_") }
}
val dir = state.annotations.collectFirst({ case TargetDirAnnotation(targetDir) => new File(targetDir) }).get
val dataDepth = p(ILADepthKey)
//dirname should be some aws-fpga synthesis directory
val topwiringannos = targetannos :+
TopWiringOutputFilesAnnotation(dir.getPath(), ILAWiringOutputFiles(dataDepth))
val topwiringannos = targetannos :+ TopWiringOutputFilesAnnotation("", ILAWiringOutputFiles(dataDepth))
val wiredState = (new TopWiringTransform).execute(state.copy(annotations = state.annotations ++ topwiringannos))
val cleanedAnnos = wiredState.annotations.filter {
case a: TopWiringOutputFilesAnnotation => false
case a: FirrtlFpgaDebugAnnotation => false
case _ => true
}
def topwiringtransform = new TopWiringTransform
topwiringtransform.execute(state.copy(annotations = state.annotations ++ topwiringannos))
wiredState.copy(annotations = cleanedAnnos ++ addedFileAnnos)
}
}

View File

@ -7,24 +7,28 @@ r_dir = $(abspath ../resources)
########################################################################
# Parameters:
# 1) PLATFORM: FPGA platform board(by default zynq)
# 2) DESIGN: Target design of midas
# 2) DRIVER_NAME: Base name for compiled drivers and ML simulators
# 3) GEN_DIR: Directory for generated source code
# 4) OUT_DIR: Directory for binary files (by default GEN_DIR)
# 5) DRIVER: software driver written by user
# 6) CLOCK_PERIOD(optional): clock period of tests
# 7) VERILATOR_FLAGS(optional): set of verilator flags to add
# 5) GEN_FILE_BASENAME: Common prefix for all GG-emitted output files
# 6) DRIVER: software driver written by user
# 7) CLOCK_PERIOD(optional): clock period of tests
# 8) VERILATOR_FLAGS(optional): set of verilator flags to add
########################################################################
ifeq ($(strip $(DESIGN)),)
$(error Define DESIGN, the target design)
ifeq ($(strip $(DRIVER_NAME)),)
$(error Define DRIVER_NAME, the base name used for compiled simulators and simulator drivers.)
endif
ifeq ($(strip $(GEN_FILE_BASENAME)),)
$(error Define GEN_FILE_BASENAME, the base name used for all Golden Gate-generated files.)
endif
ifeq ($(strip $(GEN_DIR)),)
$(error Define GEN_DIR, where all midas generated code reside)
$(error Define GEN_DIR, the directory containing all Golden Gate-generated files.)
endif
ifeq ($(strip $(TOP_DIR)),)
$(error Define TOP_DIR, the top of the chipyard directory)
endif
ifeq ($(strip $(DRIVER)),)
$(error Define DRIVER, the source code of the simulation driver)
$(error Define DRIVER, additional source files for the simulation driver)
endif
PLATFORM ?= zynq
@ -32,14 +36,10 @@ OUT_DIR ?= $(GEN_DIR)
CLOCK_PERIOD ?= 1.0
$(info platform: $(PLATFORM))
$(info target design: $(DESIGN))
$(info generated source directory: $(GEN_DIR))
$(info output directory: $(OUT_DIR))
$(info driver source files: $(DRIVER))
$(info clock period: $(CLOCK_PERIOD))
shim := FPGATop
testchip_dir=$(TOP_DIR)/generators/testchipip/src/main/resources
testchip_csrc_dir=$(testchip_dir)/testchipip/csrc
dramsim_dir=$(TOP_DIR)/tools/DRAMSim2
@ -51,16 +51,13 @@ include $(util_dir)/utils.mk
$(OUT_DIR)/dramsim2_ini: $(testchip_dir)/dramsim2_ini
ln -sf $< $@
$(OUT_DIR)/$(DESIGN).chain:
$(if $(wildcard $(GEN_DIR)/$(DESIGN).chain),cp $(GEN_DIR)/$(DESIGN).chain $@,)
override CXXFLAGS += -I$(midas_dir) -I$(util_dir)
# The trailing whitespace is important for some reason...
override LDFLAGS := $(LDFLAGS) -L$(GEN_DIR) -lstdc++ -lpthread -lgmp -lmidas
design_v := $(GEN_DIR)/$(shim).v
design_h := $(GEN_DIR)/$(DESIGN)-const.h
design_vh := $(GEN_DIR)/$(DESIGN)-const.vh
design_v := $(GEN_DIR)/$(GEN_FILE_BASENAME).sv
design_h := $(GEN_DIR)/$(GEN_FILE_BASENAME).const.h
design_vh := $(GEN_DIR)/$(GEN_FILE_BASENAME).const.vh
driver_h = $(foreach t, $(DRIVER), $(wildcard $(dir $(t))/*.h))
bridge_h := $(wildcard $(bridge_dir)/*.h)
bridge_cc := $(wildcard $(bridge_dir)/*.cc)
@ -77,12 +74,12 @@ $(platform_o): $(GEN_DIR)/%.o: $(midas_dir)/%.cc $(design_h) $(platform_h)
mkdir -p $(dir $@)
$(CXX) $(CXXFLAGS) -c -o $@ $< -include $(word 2, $^)
$(OUT_DIR)/$(DESIGN)-$(PLATFORM): $(design_h) $(lib) $(DRIVER) $(driver_h) $(platform_o) $(bridge_o)
$(OUT_DIR)/$(DRIVER_NAME)-$(PLATFORM): $(design_h) $(lib) $(DRIVER) $(driver_h) $(platform_o) $(bridge_o)
mkdir -p $(OUT_DIR)
$(CXX) $(CXXFLAGS) -include $< \
-o $@ $(DRIVER) $(lib_o) $(platform_o) $(bridge_o) $(LDFLAGS)
$(PLATFORM): $(OUT_DIR)/$(DESIGN)-$(PLATFORM) $(OUT_DIR)/$(DESIGN).chain
$(PLATFORM): $(OUT_DIR)/$(DRIVER_NAME)-$(PLATFORM)
# Sources for building MIDAS-level simulators. Must be defined before sources VCS/Verilator Makefrags
override CFLAGS += -include $(design_h)
@ -102,8 +99,8 @@ verilator_harness := emul/verilator-harness.cc
top_module := verilator_top
include rtlsim/Makefrag-verilator
verilator: $(OUT_DIR)/V$(DESIGN) $(OUT_DIR)/$(DESIGN).chain $(OUT_DIR)/dramsim2_ini
verilator-debug: $(OUT_DIR)/V$(DESIGN)-debug $(OUT_DIR)/$(DESIGN).chain $(OUT_DIR)/dramsim2_ini
verilator: $(OUT_DIR)/V$(DRIVER_NAME) $(OUT_DIR)/dramsim2_ini
verilator-debug: $(OUT_DIR)/V$(DRIVER_NAME)-debug $(OUT_DIR)/dramsim2_ini
# Add an extra wrapper source for VCS simulators
vcs_wrapper_v := $(v_dir)/vcs_top.v
@ -112,7 +109,7 @@ TB := emul
VCS_FLAGS := -e vcs_main
include rtlsim/Makefrag-vcs
vcs: $(OUT_DIR)/$(DESIGN) $(OUT_DIR)/$(DESIGN).chain $(OUT_DIR)/dramsim2_ini
vcs-debug: $(OUT_DIR)/$(DESIGN)-debug $(OUT_DIR)/$(DESIGN).chain $(OUT_DIR)/dramsim2_ini
vcs: $(OUT_DIR)/$(DRIVER_NAME) $(OUT_DIR)/dramsim2_ini
vcs-debug: $(OUT_DIR)/$(DRIVER_NAME)-debug $(OUT_DIR)/dramsim2_ini
.PHONY: $(PLATFORM) verilator verilator-debug vcs vcs-debug

View File

@ -19,7 +19,7 @@ VCS ?= vcs -full64
override VCS_FLAGS := -quiet -timescale=1ns/1ps +v2k +rad +vcs+initreg+random +vcs+lic+wait \
-notice -line +lint=all,noVCDE,noONGS,noUI -quiet -debug_pp +no_notifier -cpp $(CXX) \
-top $(TB) \
-Mdir=$(GEN_DIR)/$(DESIGN)-debug.csrc \
-Mdir=$(GEN_DIR)/$(DRIVER_NAME)-debug.csrc \
+vc+list \
-CFLAGS "$(CXXFLAGS) $(CFLAGS) -D_GNU_SOURCE -DVCS -I$(VCS_HOME)/include" \
-LDFLAGS "$(LDFLAGS)" \
@ -35,16 +35,16 @@ override VCS_FLAGS := -quiet -timescale=1ns/1ps +v2k +rad +vcs+initreg+random +v
vcs_v := $(emul_v) $(vcs_wrapper_v)
vcs_cc := $(emul_cc) $(vcs_harness)
$(OUT_DIR)/$(DESIGN): $(vcs_v) $(vcs_cc) $(emul_h)
$(OUT_DIR)/$(DRIVER_NAME): $(vcs_v) $(vcs_cc) $(emul_h)
mkdir -p $(OUT_DIR)
rm -rf $(GEN_DIR)/$(DESIGN).csrc
rm -rf $(OUT_DIR)/$(DESIGN).daidir
rm -rf $(GEN_DIR)/$(DRIVER_NAME).csrc
rm -rf $(OUT_DIR)/$(DRIVER_NAME).daidir
$(VCS) $(VCS_FLAGS) \
-o $@ $(vcs_v) $(vcs_cc)
$(OUT_DIR)/$(DESIGN)-debug: $(vcs_v) $(vcs_cc) $(emul_h)
$(OUT_DIR)/$(DRIVER_NAME)-debug: $(vcs_v) $(vcs_cc) $(emul_h)
mkdir -p $(OUT_DIR)
rm -rf $(GEN_DIR)/$(DESIGN)-debug.csrc
rm -rf $(OUT_DIR)/$(DESIGN)-debug.daidir
rm -rf $(GEN_DIR)/$(DRIVER_NAME)-debug.csrc
rm -rf $(OUT_DIR)/$(DRIVER_NAME)-debug.daidir
$(VCS) $(VCS_FLAGS) +define+DEBUG \
-o $@ $(vcs_v) $(vcs_cc)

View File

@ -5,7 +5,7 @@
# Compulsory variables:
# OUT_DIR: See Makefile
# GEN_DIR: See Makefile
# DESIGN: See Makefile
# DRIVER_NAME: See Makefile
# emul_cc: C++ sources
# emul_h: C++ headers
# emul_v: verilog sources and headers
@ -33,18 +33,18 @@ override VERILATOR_FLAGS := \
-LDFLAGS "$(LDFLAGS) " \
$(VERILATOR_FLAGS)
$(OUT_DIR)/V$(DESIGN): $(verilator_v) $(verilator_cc) $(emul_h)
$(OUT_DIR)/V$(DRIVER_NAME): $(verilator_v) $(verilator_cc) $(emul_h)
mkdir -p $(OUT_DIR)
rm -rf $(GEN_DIR)/V$(DESIGN).csrc
$(VERILATOR) $(VERILATOR_FLAGS) -Mdir $(GEN_DIR)/V$(DESIGN).csrc \
-CFLAGS "-include $(GEN_DIR)/V$(DESIGN).csrc/V$(top_module).h" \
rm -rf $(GEN_DIR)/V$(DRIVER_NAME).csrc
$(VERILATOR) $(VERILATOR_FLAGS) -Mdir $(GEN_DIR)/V$(DRIVER_NAME).csrc \
-CFLAGS "-include $(GEN_DIR)/V$(DRIVER_NAME).csrc/V$(top_module).h" \
-o $@ $(verilator_v) $(verilator_conf) $(verilator_cc)
$(MAKE) -C $(GEN_DIR)/V$(DESIGN).csrc -f V$(top_module).mk
$(MAKE) -C $(GEN_DIR)/V$(DRIVER_NAME).csrc -f V$(top_module).mk
$(OUT_DIR)/V$(DESIGN)-debug: $(verilator_v) $(verilator_cc) $(emul_h)
$(OUT_DIR)/V$(DRIVER_NAME)-debug: $(verilator_v) $(verilator_cc) $(emul_h)
mkdir -p $(OUT_DIR)
rm -rf $(GEN_DIR)/V$(DESIGN)-debug.csrc
$(VERILATOR) $(VERILATOR_FLAGS) --trace -Mdir $(GEN_DIR)/V$(DESIGN)-debug.csrc \
-CFLAGS "-include $(GEN_DIR)/V$(DESIGN)-debug.csrc/V$(top_module).h" \
rm -rf $(GEN_DIR)/V$(DRIVER_NAME)-debug.csrc
$(VERILATOR) $(VERILATOR_FLAGS) --trace -Mdir $(GEN_DIR)/V$(DRIVER_NAME)-debug.csrc \
-CFLAGS "-include $(GEN_DIR)/V$(DRIVER_NAME)-debug.csrc/V$(top_module).h" \
-o $@ $(verilator_v) $(verilator_conf) $(verilator_cc)
$(MAKE) -C $(GEN_DIR)/V$(DESIGN)-debug.csrc -f V$(top_module).mk
$(MAKE) -C $(GEN_DIR)/V$(DRIVER_NAME)-debug.csrc -f V$(top_module).mk

View File

@ -257,7 +257,8 @@ class FPGATopImp(outer: FPGATop)(implicit p: Parameters) extends LazyModuleImp(o
}
outer.genCtrlIO(ctrl)
outer.printHostDRAMSummary
outer.printHostDRAMSummary()
outer.emitDefaultPlusArgsFile()
val addrConsts = dmaAddrMap.map {
case AddrMapEntry(name, MemRange(addr, _, _)) =>

View File

@ -552,7 +552,6 @@ class FASEDMemoryTimingModel(completeConfig: CompleteConfig, hostParams: Paramet
genCRFile()
dontTouch(targetFire)
chisel3.experimental.annotate(Fame1ChiselAnnotation(model, "targetFire"))
getDefaultSettings("runtime.conf")
override def genHeader(base: BigInt, sb: StringBuilder) {
def genCPPmap(mapName: String, map: Map[String, BigInt]): String = {
@ -581,29 +580,30 @@ class FASEDMemoryTimingModel(completeConfig: CompleteConfig, hostParams: Paramet
case None => println(" No LLC Model Instantiated\n")
}
}
}
// Accepts an elaborated memory model and generates a runtime configuration for it
private def emitSettings(fileName: String, settings: Seq[(String, String)])(implicit p: Parameters): Unit = {
val file = new File(p(OutputDir), fileName)
val writer = new FileWriter(file, wId != 0)
settings.foreach({
case (field, value) => writer.write(s"+mm_${field}_${wId}=${value}\n")
})
writer.close
}
/**
* Disambiguates between multiple fased instances by using wId (this
* increments for each instantion of widgets of the same class), which
* is defined in Widget
*/
def settingsToString(settings: Seq[(String, String)]): String =
settings.map { case (field, value) => s"+mm_${field}_${wId}=${value}" }.mkString("\n")
def getSettings(fileName: String)(implicit p: Parameters) {
println("\nGenerating a Midas Memory Model Configuration File")
val functionalModelSettings = funcModelRegs.getFuncModelSettings()
val timingModelSettings = model.io.mmReg.getTimingModelSettings()
emitSettings(fileName, functionalModelSettings ++ timingModelSettings)
}
/**
* Used by the runtime configuration generator, and not the main GG flow.
*/
def getSettings: String = {
println("\nGenerating a Midas Memory Model Configuration File")
val functionalModelSettings = module.funcModelRegs.getFuncModelSettings()
val timingModelSettings = module.model.io.mmReg.getTimingModelSettings()
settingsToString(functionalModelSettings ++ timingModelSettings)
}
def getDefaultSettings(fileName: String)(implicit p: Parameters) {
val functionalModelSettings = funcModelRegs.getDefaults()
val timingModelSettings = model.io.mmReg.getDefaults()
emitSettings(fileName, functionalModelSettings ++ timingModelSettings)
}
override def defaultPlusArgs: Option[String] = {
val functionalModelSettings = module.funcModelRegs.getDefaults()
val timingModelSettings = module.model.io.mmReg.getDefaults()
Some(settingsToString(functionalModelSettings ++ timingModelSettings))
}
}

View File

@ -24,39 +24,39 @@ import freechips.rocketchip.diplomacy.LazyModule
import midas.core._
import midas.platform.PlatformShim
import midas.stage.{OutputFileBuilder, GoldenGateOutputFileAnnotation}
private[passes] class SimulationMapping(targetName: String) extends firrtl.Transform {
def inputForm = LowForm
def outputForm = HighForm
override def name = "[Golden Gate] Simulation Mapping"
private def dumpHeader(c: PlatformShim, dir: File) {
private def generateHeaderAnnos(c: PlatformShim): Seq[GoldenGateOutputFileAnnotation] = {
def vMacro(arg: (String, Long)): String = s"`define ${arg._1} ${arg._2}\n"
val csb = new StringBuilder
val csb = new OutputFileBuilder(
"""// Golden Gate-generated Driver Header
|// This contains target-specific preprocessor macro definitions,
|// and encodes all required bridge metadata to instantiate bridge drivers.
|""".stripMargin,
fileSuffix = ".const.h")
csb append "#ifndef __%s_H\n".format(targetName.toUpperCase)
csb append "#define __%s_H\n".format(targetName.toUpperCase)
c.genHeader(csb, targetName)
c.genHeader(csb.getBuilder, targetName)
csb append "#endif // __%s_H\n".format(targetName.toUpperCase)
val vsb = new StringBuilder
val vsb = new OutputFileBuilder(
"""// Golden Gate-generated Verilog Header
|// This file encodes variable width fields used in MIDAS-level simulation
|// and is not used in FPGA compilation flows.
|""".stripMargin,
fileSuffix = ".const.vh")
vsb append "`ifndef __%s_H\n".format(targetName.toUpperCase)
vsb append "`define __%s_H\n".format(targetName.toUpperCase)
c.top.module.headerConsts map vMacro addString vsb
c.top.module.headerConsts map vMacro foreach vsb.append
vsb append "`endif // __%s_H\n".format(targetName.toUpperCase)
val ch = new FileWriter(new File(dir, s"${targetName}-const.h"))
val vh = new FileWriter(new File(dir, s"${targetName}-const.vh"))
try {
ch write csb.result
vh write vsb.result
} finally {
ch.close
vh.close
csb.clear
vsb.clear
}
Seq(csb.toAnnotation, vsb.toAnnotation)
}
// Note: this only runs on the SimulationWrapper Module
@ -110,9 +110,9 @@ private[passes] class SimulationMapping(targetName: String) extends firrtl.Trans
}).getOrElse(throw new Exception("TargetBoxAnnotation not found or annotated top module!"))
val targetBoxParent = targetBoxInstTarget.encapsulatingModule
val targetBoxInst = targetBoxInstTarget.instance
val modules = innerCircuit.modules ++ (outerCircuit.modules flatMap
init(innerCircuit.info, innerCircuit.main, targetType, targetBoxParent, targetBoxInst))
val modules = (outerCircuit.modules flatMap
init(innerCircuit.info, innerCircuit.main, targetType, targetBoxParent, targetBoxInst)) ++
innerCircuit.modules
// Rename the annotations from the inner module, which are using an obsolete CircuitName
val renameMap = RenameMap(
Map(CircuitName(innerCircuit.main) -> Seq(CircuitName(outerCircuit.main))))
@ -129,8 +129,7 @@ private[passes] class SimulationMapping(targetName: String) extends firrtl.Trans
renames = Some(renameMap)
)
writeState(linkedState, "post-sim-mapping.fir")
dumpHeader(shim, p(OutputDir))
linkedState
linkedState.copy(annotations = linkedState.annotations ++ generateHeaderAnnos(shim))
}
}

View File

@ -48,3 +48,16 @@ object RuntimeConfigNameAnnotation extends HasShellOptions {
shortOption = Some("ggrc"),
helpValueName = Some("<filename>") ) )
}
case class OutputBaseFilenameAnnotation(name: String) extends NoTargetAnnotation with GoldenGateOption
object OutputBaseFilenameAnnotation extends HasShellOptions {
val options = Seq(
new ShellOption[String](
longOption = "output-filename-base",
toAnnotationSeq = (a: String) => Seq(OutputBaseFilenameAnnotation(a)),
helpText = "Specifies the base (prefix) used on Golden Gate generated files.",
shortOption = Some("ofb"),
helpValueName = Some("<output-filename-base>") ) )
}

View File

@ -8,6 +8,7 @@ trait GoldenGateCli { this: Shell =>
parser.note("Golden Gate Compiler Options")
Seq(ConfigPackageAnnotation,
ConfigStringAnnotation,
OutputBaseFilenameAnnotation,
firrtl.stage.FirrtlFileAnnotation,
firrtl.stage.OutputFileAnnotation,
firrtl.stage.FirrtlSourceAnnotation,

View File

@ -40,7 +40,7 @@ class GoldenGateCompilerPhase extends Phase {
// Lower and emit simulator RTL and run user-requested host-transforms
val hostLoweringCompiler = new Compiler(
Dependency[firrtl.VerilogEmitter] +:
Dependency[firrtl.SystemVerilogEmitter] +:
p(HostTransforms),Forms.LowForm)
logger.info("Post-GG Host Transformation Ordering\n")
logger.info(hostLoweringCompiler.prettyPrint(" "))

View File

@ -5,28 +5,36 @@ package midas.stage
import firrtl.annotations.{NoTargetAnnotation, Annotation}
import firrtl.options.{CustomFileEmission}
import chisel3.experimental.{annotate, ChiselAnnotation}
trait GoldenGateFileEmission extends CustomFileEmission { this: Annotation =>
// workaround CustomFileEmission's requirement that suffixes begin with ".".
// by shadowing the same feature, and appending it ourselves. This is the
// easiest way to preserve most of the existing output file names.
def fileSuffix: String
final def suffix = None
override def baseFileName(annotations: firrtl.AnnotationSeq) = {
val baseName = annotations.collectFirst{ case OutputBaseFileNameAnnotation(name) => name }.get
baseName + fileSuffix
annotations.collectFirst{ case OutputBaseFilenameAnnotation(name) => name }.get
}
}
/**
* A generic wrapper for output files that have no targets.
*
* @param body the body of the file
* @param fileSuffix The string to append to base output file name
*
*/
case class GoldenGateOutputFileAnnotation(body: String, fileSuffix: String)
extends NoTargetAnnotation with GoldenGateFileEmission {
def suffix = Some(fileSuffix)
def getBytes = body.getBytes
}
object GoldenGateOutputFileAnnotation {
/**
* Sugar to add a new output file from a chisel source (e.g., in a bridge, platform shim)
*/
def annotateFromChisel(body: String, fileSuffix: String): Unit = {
annotate(new ChiselAnnotation { def toFirrtl = GoldenGateOutputFileAnnotation(body, fileSuffix) })
}
}
/**
* Wraps a StringBuilder to incrementally build up an output file annotation.
*/

View File

@ -10,13 +10,19 @@ import midas.platform.PlatformShim
import freechips.rocketchip.diplomacy.{LazyModule, ValName}
import firrtl.ir.Port
import firrtl.annotations.ReferenceTarget
import firrtl.annotations.{ReferenceTarget, NoTargetAnnotation}
import firrtl.{Transform, CircuitState, AnnotationSeq}
import firrtl.options.{Phase, TargetDirAnnotation, Dependency}
import firrtl.options.{Phase, TargetDirAnnotation, Dependency, CustomFileEmission}
import java.io.{File, FileWriter, Writer}
import logger._
private [stage] case class RuntimeConfigurationFile(name: String, body: String) extends NoTargetAnnotation with CustomFileEmission {
override def suffix = None
def baseFileName(annos: AnnotationSeq) = name
def getBytes = body.getBytes
}
class RuntimeConfigGenerationPhase extends Phase {
override val prerequisites = Seq(Dependency[CreateParametersInstancePhase])
@ -32,11 +38,12 @@ class RuntimeConfigGenerationPhase extends Phase {
val fasedBridges = shim.top.bridgeModuleMap.values.collect { case f: FASEDMemoryTimingModel => f }
// Since presently all memory models share the same runtime configuration. Grab only the first
// FASED BridgeAnnotation, and use that to elaborate a memory model
fasedBridges.headOption.map({ lm =>
lazy val fasedBridge = lm.module
chisel3.stage.ChiselStage.elaborate(fasedBridge)
fasedBridge.getSettings(runtimeConfigName)
val settings = fasedBridges.headOption.map({ lm =>
lazy val fasedBridge = lm
chisel3.stage.ChiselStage.elaborate(fasedBridge.module)
fasedBridge.getSettings
})
annotations
RuntimeConfigurationFile(runtimeConfigName, settings.getOrElse("\n")) +: annotations
}
}

View File

@ -1,4 +1,4 @@
// See LICENSE.SiFive for license details.
// See LICENSE for license details.
package midas.widgets

View File

@ -3,6 +3,8 @@
package midas
package widgets
import midas.stage.GoldenGateOutputFileAnnotation
import chisel3._
import chisel3.util._
import chisel3.experimental.DataMirror
@ -55,6 +57,8 @@ abstract class Widget()(implicit p: Parameters) extends LazyModule()(p) {
def memRegionSize = customSize.getOrElse(BigInt(1 << log2Up(module.numRegs * (module.io.ctrl.nastiXDataBits/8))))
def printCRs = module.crRegistry.printCRs
def defaultPlusArgs: Option[String] = None
}
abstract class WidgetImp(wrapper: Widget) extends LazyModuleImp(wrapper) {
@ -254,4 +258,17 @@ trait HasWidgets {
val base = (addrMap(w.getWName).start >> log2Up(channelWidth/8))
base + w.getCRAddr(crName)
}
/**
* Iterates through all bound widgets requesting default plusArgs if
* applicable, which are then serialized to a file. This is mostly useful
* for bridges that do not have defaults baked into the driver, such as
* FASED, where plus args _must_ be provided.
*/
def emitDefaultPlusArgsFile(): Unit =
GoldenGateOutputFileAnnotation.annotateFromChisel(
// Append an extra \n to prevent the file from being empty.
body = widgets.map(_.defaultPlusArgs).flatten.mkString("\n") + "\n",
fileSuffix = ".runtime.conf"
)
}

View File

@ -19,6 +19,9 @@ name_tuple := $(DESIGN)-$(TARGET_CONFIG)-$(PLATFORM_CONFIG)
GENERATED_DIR := $(firesim_base_dir)/generated-src/$(PLATFORM)/$(name_tuple)
OUTPUT_DIR := $(firesim_base_dir)/output/$(PLATFORM)/$(name_tuple)
# This is prefix is currently assumed by the fpga build flow
BASE_FILE_NAME := FireSim-generated
##################
# RTL Generation #
##################
@ -26,10 +29,6 @@ long_name := $(DESIGN_PACKAGE).$(DESIGN).$(TARGET_CONFIG)
FIRRTL_FILE := $(GENERATED_DIR)/$(long_name).fir
ANNO_FILE := $(GENERATED_DIR)/$(long_name).anno.json
VERILOG := $(GENERATED_DIR)/FPGATop.v
HEADER := $(GENERATED_DIR)/$(DESIGN)-const.h
CONF_NAME ?= runtime.conf
firesim_sbt_project := {file:${firesim_base_dir}/}firesim
chisel_src_dirs = \
$(addprefix $(firesim_base_dir)/,. midas midas/targetutils firesim-lib) \

View File

@ -19,6 +19,9 @@ name_tuple := $(DESIGN)-$(TARGET_CONFIG)-$(PLATFORM_CONFIG)
GENERATED_DIR := $(firesim_base_dir)/generated-src/$(PLATFORM)/$(name_tuple)
OUTPUT_DIR := $(firesim_base_dir)/output/$(PLATFORM)/$(name_tuple)
# This is prefix is currently assumed by the fpga build flow
BASE_FILE_NAME := FireSim-generated
##################
# RTL Generation #
##################
@ -26,9 +29,6 @@ long_name := $(DESIGN_PACKAGE).$(DESIGN).$(TARGET_CONFIG)
FIRRTL_FILE := $(GENERATED_DIR)/$(long_name).fir
ANNO_FILE := $(GENERATED_DIR)/$(long_name).anno.json
VERILOG := $(GENERATED_DIR)/FPGATop.v
HEADER := $(GENERATED_DIR)/$(DESIGN)-const.h
ifdef FIRESIM_STANDALONE
firesim_sbt_project := {file:${chipyard_dir}}firechip
@ -72,7 +72,7 @@ DROMAJO_DTB = $(GENERATED_DIR)/$(long_name).dtb
$(DROMAJO_LIB):
$(MAKE) -C $(DROMAJO_DIR)
$(DROMAJO_LONG_H) $(DTS_FILE): $(VERILOG)
$(DROMAJO_LONG_H) $(DTS_FILE): $(simulator_verilog)
$(DROMAJO_H): $(DROMAJO_LONG_H)
rm -rf $(DROMAJO_H)
@ -133,7 +133,7 @@ DEFAULT_MIDAS_VERILATOR_FLAGS = \
# AJG: this must be evaluated after verilog generation to work (hence the =)
EXTRA_VERILATOR_FLAGS = \
$(shell if ! grep -iq "module.*cva6" $(VERILOG); then echo "$(DEFAULT_MIDAS_VERILATOR_FLAGS)"; else echo "$(CVA6_VERILATOR_FLAGS)"; fi)
$(shell if ! grep -iq "module.*cva6" $(simulator_verilog); then echo "$(DEFAULT_MIDAS_VERILATOR_FLAGS)"; else echo "$(CVA6_VERILATOR_FLAGS)"; fi)
################################################################
# SW RTL Simulation Args -- for MIDAS- & FPGA-level Simulation #

View File

@ -14,6 +14,9 @@ name_tuple := $(DESIGN)-$(TARGET_CONFIG)-$(PLATFORM_CONFIG)
GENERATED_DIR := $(firesim_base_dir)/generated-src/$(PLATFORM)/$(name_tuple)
OUTPUT_DIR := $(firesim_base_dir)/output/$(PLATFORM)/$(name_tuple)
# This is prefix is currently assumed by the fpga build flow
BASE_FILE_NAME := FireSim-generated
##########################
# RTL Generation #
##########################
@ -21,9 +24,6 @@ long_name := $(DESIGN_PACKAGE).$(DESIGN).$(TARGET_CONFIG)
FIRRTL_FILE := $(GENERATED_DIR)/$(long_name).fir
ANNO_FILE := $(GENERATED_DIR)/$(long_name).anno.json
VERILOG := $(GENERATED_DIR)/FPGATop.v
HEADER := $(GENERATED_DIR)/$(DESIGN)-const.h
ifdef FIRESIM_STANDALONE
firesim_sbt_project := firesim
else
@ -37,8 +37,6 @@ chisel_src_dirs = \
chisel_srcs = $(foreach submodule,$(chisel_src_dirs),\
$(shell find $(submodule)/ -iname "[!.]*.scala" -print 2> /dev/null | grep 'src/main/scala'))
CONF_NAME ?= runtime.conf
SIM_RUNTIME_CONF ?= $(GENERATED_DIR)/$(CONF_NAME)
mem_model_args = $(shell cat $(SIM_RUNTIME_CONF))
COMMON_SIM_ARGS ?= $(mem_model_args)
@ -51,8 +49,6 @@ $(FIRRTL_FILE) $(ANNO_FILE): $(chisel_srcs) $(FIRRTL_JAR) $(SCALA_BUILDTOOL_DEPS
--name $(long_name) \
--top-module $(DESIGN_PACKAGE).$(DESIGN) \
--legacy-configs $(TARGET_CONFIG_PACKAGE):$(TARGET_CONFIG))
# Remove once runtime conf generation is generalized, and something is always emitted
touch $(GENERATED_DIR)/$(CONF_NAME)
##########################
# Driver Sources & Flags #
@ -75,7 +71,7 @@ TARGET_LD_FLAGS :=
# PointerChaser requires a custom memory initialization
ifeq ($(DESIGN),PointerChaser)
LOADMEM ?= $(GENERATED_DIR)/mem_init.hex
ARGS ?= `cat runtime.conf`
ARGS ?= `cat $(SIM_RUNTIME_CONF)`
$(LOADMEM): src/main/resources/midasexamples/generate_memory_init.py
$< --output_file $@

View File

@ -1,6 +1,18 @@
# See LICENSE for license details.
# FireSim MAKEFRAG interface - Compulsory variables follow
# FireSim Target Agnostic Make Fragment
#
# Defines make targets for:
# - invoking Golden Gate (phony: verilog / compile)
# - building a simulation driver (phony: f1)
# - populating an FPGA build directory (phony: replace-rtl)
# - generating new runtime configurations (phony: conf)
# - compiling meta-simulators (phony: verilator, vcs, verilator-debug, vcs-debug)
#
# The prefix used for all Golden Gate-generated files
BASE_FILE_NAME ?=
# The directory into which generated verilog and headers will be dumped
# RTL simulations will also be built here
GENERATED_DIR ?=
@ -9,16 +21,7 @@ OUTPUT_DIR ?=
# Root name for generated binaries
DESIGN ?=
# SOURCE FILES
# Driver source files
DRIVER_CC ?=
DRIVER_H ?=
# Simulation memory map emitted by the MIDAS compiler
HEADER ?=
# The midas-generated simulator RTL which will be baked into the FPGA shell project
VERILOG ?=
# The target's FIRRTL and associated anotations
# The target's FIRRTL and associated anotations; inputs to Golden Gate
FIRRTL_FILE ?=
ANNO_FILE ?=
@ -27,12 +30,16 @@ PLATFORM_CONFIG_PACKAGE ?= firesim.midasexamples
PLATFORM_CONFIG ?= DefaultF1Config
# The name of the generated runtime configuration file
CONF_NAME ?= runtime.conf
CONF_NAME ?= $(BASE_FILE_NAME).runtime.conf
# The host platform type
PLATFORM ?= f1
# The host platform type, currently only f1 is supported
PLATFORM ?=
# Target-specific CXX and LD flags
# Driver source files
DRIVER_CC ?=
DRIVER_H ?=
# Target-specific CXX and LD flags for compiling the driver and meta-simulators
TARGET_CXX_FLAGS ?=
TARGET_LD_FLAGS ?=
@ -43,6 +50,11 @@ midas_cc = $(shell find $(simif_dir) -name "*.cc")
common_cxx_flags := $(TARGET_CXX_FLAGS) -Wno-unused-variable
common_ld_flags := $(TARGET_LD_FLAGS) -lrt
# Simulation memory map emitted by the MIDAS compiler
header := $(GENERATED_DIR)/$(BASE_FILE_NAME).const.h
# The midas-generated simulator RTL which will be baked into the FPGA shell project
simulator_verilog := $(GENERATED_DIR)/$(BASE_FILE_NAME).sv
####################################
# Golden Gate Invocation #
####################################
@ -51,20 +63,30 @@ firesim_root_sbt_project := {file:$(firesim_base_dir)}firesim
# extracted used to generate new runtime configurations.
fame_annos := $(GENERATED_DIR)/post-bridge-extraction.json
.PHONY: verilog compile
verilog: $(simulator_verilog)
compile: $(simulator_verilog)
# empty recipe to help make understand multiple targets come from single recipe invocation
# without using the new (4.3) '&:' grouped targets see https://stackoverflow.com/a/41710495
.SECONDARY: $(simulator_verilog).intermediate
$(simulator_verilog) $(header) $(fame_annos): $(simulator_verilog).intermediate ;
# Disable FIRRTL 1.4 deduplication because it creates multiple failures
# Run the 1.3 version instead (checked-in). If dedup must be completely disabled,
# pass --no-legacy-dedup as well
$(VERILOG) $(HEADER) $(fame_annos): $(FIRRTL_FILE) $(ANNO_FILE) $(SCALA_BUILDTOOL_DEPS)
$(simulator_verilog).intermediate: $(FIRRTL_FILE) $(ANNO_FILE) $(SCALA_BUILDTOOL_DEPS)
$(call run_scala_main,$(firesim_sbt_project),midas.stage.GoldenGateMain,\
-o $(VERILOG) -i $(FIRRTL_FILE) -td $(GENERATED_DIR) \
-o $(simulator_verilog) -i $(FIRRTL_FILE) -td $(GENERATED_DIR) \
-faf $(ANNO_FILE) \
-ggcp $(PLATFORM_CONFIG_PACKAGE) \
-ggcs $(PLATFORM_CONFIG) \
--output-filename-base $(BASE_FILE_NAME) \
--no-dedup \
-E verilog \
-E sverilog \
)
grep -sh ^ $(GENERATED_DIR)/firrtl_black_box_resource_files.f | \
xargs cat >> $(VERILOG) # Append blackboxes to FPGA wrapper, if any
xargs cat >> $(simulator_verilog) # Append blackboxes to FPGA wrapper, if any
####################################
# Runtime-Configuration Generation #
@ -77,8 +99,6 @@ $(VERILOG) $(HEADER) $(fame_annos): $(FIRRTL_FILE) $(ANNO_FILE) $(SCALA_BUILDTOO
.PHONY: conf
conf: $(fame_annos)
mkdir -p $(GENERATED_DIR)
# Runtime configuration generator must run under SBT currently; When
# launched via bloop some Console input and output is lost.
cd $(base_dir) && $(SBT) "project $(firesim_sbt_project)" "runMain midas.stage.RuntimeConfigGeneratorMain \
-td $(GENERATED_DIR) \
-faf $(fame_annos) \
@ -99,12 +119,12 @@ verilator_debug = $(GENERATED_DIR)/V$(DESIGN)-debug
$(verilator) $(verilator_debug): export CXXFLAGS := $(CXXFLAGS) $(common_cxx_flags) $(VERILATOR_CXXOPTS) -D RTLSIM
$(verilator) $(verilator_debug): export LDFLAGS := $(LDFLAGS) $(common_ld_flags)
$(verilator): $(HEADER) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h) $(VERILOG)
$(MAKE) $(VERILATOR_MAKEFLAGS) -C $(simif_dir) verilator PLATFORM=$(PLATFORM) DESIGN=$(DESIGN) \
$(verilator): $(header) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h) $(simulator_verilog)
$(MAKE) $(VERILATOR_MAKEFLAGS) -C $(simif_dir) verilator PLATFORM=$(PLATFORM) DRIVER_NAME=$(DESIGN) GEN_FILE_BASENAME=$(BASE_FILE_NAME) \
GEN_DIR=$(GENERATED_DIR) DRIVER="$(DRIVER_CC)" TOP_DIR=$(chipyard_dir) VERILATOR_FLAGS="$(EXTRA_VERILATOR_FLAGS)"
$(verilator_debug): $(HEADER) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h) $(VERILOG)
$(MAKE) $(VERILATOR_MAKEFLAGS) -C $(simif_dir) verilator-debug PLATFORM=$(PLATFORM) DESIGN=$(DESIGN) \
$(verilator_debug): $(header) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h) $(simulator_verilog)
$(MAKE) $(VERILATOR_MAKEFLAGS) -C $(simif_dir) verilator-debug PLATFORM=$(PLATFORM) DRIVER_NAME=$(DESIGN) GEN_FILE_BASENAME=$(BASE_FILE_NAME) \
GEN_DIR=$(GENERATED_DIR) DRIVER="$(DRIVER_CC)" TOP_DIR=$(chipyard_dir) VERILATOR_FLAGS="$(EXTRA_VERILATOR_FLAGS)"
.PHONY: verilator verilator-debug
@ -123,12 +143,12 @@ vcs_debug = $(GENERATED_DIR)/$(DESIGN)-debug
$(vcs) $(vcs_debug): export CXXFLAGS := $(CXXFLAGS) $(common_cxx_flags) $(VCS_CXXOPTS) -I$(VCS_HOME)/include -D RTLSIM
$(vcs) $(vcs_debug): export LDFLAGS := $(LDFLAGS) $(common_ld_flags)
$(vcs): $(HEADER) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h) $(VERILOG)
$(MAKE) -C $(simif_dir) vcs PLATFORM=$(PLATFORM) DESIGN=$(DESIGN) \
$(vcs): $(header) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h) $(simulator_verilog)
$(MAKE) -C $(simif_dir) vcs PLATFORM=$(PLATFORM) DRIVER_NAME=$(DESIGN) GEN_FILE_BASENAME=$(BASE_FILE_NAME) \
GEN_DIR=$(GENERATED_DIR) DRIVER="$(DRIVER_CC)" TOP_DIR=$(chipyard_dir)
$(vcs_debug): $(HEADER) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h) $(VERILOG)
$(MAKE) -C $(simif_dir) vcs-debug PLATFORM=$(PLATFORM) DESIGN=$(DESIGN) \
$(vcs_debug): $(header) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h) $(simulator_verilog)
$(MAKE) -C $(simif_dir) vcs-debug PLATFORM=$(PLATFORM) DRIVER_NAME=$(DESIGN) GEN_FILE_BASENAME=$(BASE_FILE_NAME) \
GEN_DIR=$(GENERATED_DIR) DRIVER="$(DRIVER_CC)" TOP_DIR=$(chipyard_dir)
.PHONY: vcs vcs-debug
@ -140,12 +160,8 @@ vcs-debug: $(vcs_debug)
############################
DRIVER_CXXOPTS ?= -O2
$(OUTPUT_DIR)/$(DESIGN).chain: $(VERILOG)
mkdir -p $(OUTPUT_DIR)
$(if $(wildcard $(GENERATED_DIR)/$(DESIGN).chain),cp $(GENERATED_DIR)/$(DESIGN).chain $@,)
$(PLATFORM) = $(OUTPUT_DIR)/$(DESIGN)-$(PLATFORM)
$(PLATFORM): $($(PLATFORM)) $(OUTPUT_DIR)/$(DESIGN).chain
$(PLATFORM): $($(PLATFORM))
fpga_dir = $(firesim_base_dir)/../platforms/$(PLATFORM)/aws-fpga
@ -154,11 +170,12 @@ $(f1): export CXXFLAGS := $(CXXFLAGS) $(common_cxx_flags) $(DRIVER_CXXOPTS) -I$(
$(f1): export LDFLAGS := $(LDFLAGS) $(common_ld_flags) -lfpga_mgmt
# Compile Driver
$(f1): $(HEADER) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h) $(runtime_conf)
$(f1): $(header) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h)
mkdir -p $(OUTPUT_DIR)/build
cp $(HEADER) $(OUTPUT_DIR)/build/
cp $(header) $(OUTPUT_DIR)/build/
# The manager expects to find the default conf in output/ by this name
cp -f $(GENERATED_DIR)/$(CONF_NAME) $(OUTPUT_DIR)/runtime.conf
$(MAKE) -C $(simif_dir) f1 PLATFORM=f1 DESIGN=$(DESIGN) \
$(MAKE) -C $(simif_dir) f1 PLATFORM=f1 DRIVER_NAME=$(DESIGN) GEN_FILE_BASENAME=$(BASE_FILE_NAME) \
GEN_DIR=$(OUTPUT_DIR)/build OUT_DIR=$(OUTPUT_DIR) DRIVER="$(DRIVER_CC)" \
TOP_DIR=$(chipyard_dir)
@ -169,38 +186,27 @@ board_dir := $(fpga_dir)/hdk/cl/developer_designs
fpga_work_dir := $(board_dir)/cl_$(name_tuple)
fpga_build_dir := $(fpga_work_dir)/build
verif_dir := $(fpga_work_dir)/verif
fpga_v := $(fpga_work_dir)/design/cl_firesim_generated.sv
ila_work_dir := $(fpga_work_dir)/design/ila_files/
fpga_vh := $(fpga_work_dir)/design/cl_firesim_generated_defines.vh
fpga_tcl_env := $(fpga_work_dir)/design/cl_firesim_generated_env.tcl
repo_state := $(fpga_work_dir)/design/repo_state
# Enumerates the subset of generated files that must be copied over for FPGA compilation
fpga_delivery_files = $(addprefix $(fpga_work_dir)/design/$(BASE_FILE_NAME), \
.sv .defines.vh .env.tcl \
.ila_insert_inst.v .ila_insert_ports.v .ila_insert_wires.v .ila_insert_vivado.tcl)
$(fpga_work_dir)/stamp: $(shell find $(board_dir)/cl_firesim -name '*')
mkdir -p $(@D)
cp -rf $(board_dir)/cl_firesim -T $(fpga_work_dir)
touch $@
$(fpga_v): $(VERILOG) $(fpga_work_dir)/stamp
$(repo_state): $(simulator_verilog) $(fpga_work_dir)/stamp
$(firesim_base_dir)/../scripts/repo_state_summary.sh > $(repo_state)
cp -f $< $@
sed -i "s/\$$random/64'b0/g" $@
sed -i "s/\(^ *\)fatal;\( *$$\)/\1fatal(0, \"\");\2/g" $@
$(fpga_vh): $(VERILOG) $(fpga_work_dir)/stamp
$(fpga_work_dir)/design/$(BASE_FILE_NAME)%: $(simulator_verilog) $(fpga_work_dir)/stamp
cp -f $(GENERATED_DIR)/$(@F) $@
$(fpga_tcl_env): $(VERILOG) $(fpga_work_dir)/stamp
cp -f $(GENERATED_DIR)/$(@F) $@
.PHONY: $(ila_work_dir)
$(ila_work_dir): $(verilog) $(fpga_work_dir)/stamp
cp -f $(GENERATED_DIR)/firesim_ila_insert_* $(fpga_work_dir)/design/ila_files/
sed -i "s/\$$random/64'b0/g" $(fpga_work_dir)/design/ila_files/*
sed -i "s/\(^ *\)fatal;\( *$$\)/\1fatal(0, \"\");\2/g" $(fpga_work_dir)/design/ila_files/*
# Goes as far as setting up the build directory without running the cad job
# Used by the manager before passing a build to a remote machine
replace-rtl: $(fpga_v) $(ila_work_dir) $(fpga_vh) $(fpga_tcl_env)
replace-rtl: $(fpga_delivery_files)
.PHONY: replace-rtl
@ -210,7 +216,7 @@ $(firesim_base_dir)/scripts/checkpoints/$(target_sim_tuple): $(fpga_work_dir)/st
# Runs a local fpga-bitstream build. Strongly consider using the manager instead.
fpga: export CL_DIR := $(fpga_work_dir)
fpga: $(fpga_v) $(base_dir)/scripts/checkpoints/$(target_sim_tuple)
fpga: $(fpga_delivery_files) $(base_dir)/scripts/checkpoints/$(target_sim_tuple)
cd $(fpga_build_dir)/scripts && ./aws_build_dcp_from_cl.sh -notify
@ -228,8 +234,8 @@ xsim = $(GENERATED_DIR)/$(DESIGN)-$(PLATFORM)
$(xsim): export CXXFLAGS := $(CXXFLAGS) $(common_cxx_flags) -D SIMULATION_XSIM -D NO_MAIN
$(xsim): export LDFLAGS := $(LDFLAGS) $(common_ld_flags)
$(xsim): $(HEADER) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h)
$(MAKE) -C $(simif_dir) f1 PLATFORM=f1 DESIGN=$(DESIGN) \
$(xsim): $(header) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h)
$(MAKE) -C $(simif_dir) f1 PLATFORM=f1 DRIVER_NAME=$(DESIGN) GEN_FILE_BASENAME=$(BASE_FILE_NAME) \
GEN_DIR=$(GENERATED_DIR) OUT_DIR=$(GENERATED_DIR) DRIVER="$(DRIVER_CC)" \
TOP_DIR=$(chipyard_dir)
@ -287,10 +293,9 @@ clean:
veryclean:
rm -rf generated-src output
tags: $(HEADER) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h)
tags: $(header) $(DRIVER_CC) $(DRIVER_H) $(midas_cc) $(midas_h)
ctags -R --exclude=@.ctagsignore .
.PHONY: default verilog compile
.PHONY: $(PLATFORM)-driver fpga
.PHONY: mostlyclean clean