Merge pull request #197 from firesim/print-synthesis
Enable Endpointed Print synthesis
This commit is contained in:
commit
5be11e3861
|
@ -10,31 +10,32 @@
|
|||
# own images.
|
||||
|
||||
[fireboom-singlecore-nic-ddr3-llc4mb]
|
||||
agfi=agfi-05c7620b62b901690
|
||||
agfi=agfi-00857d0de5aa1d7b7
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
||||
[fireboom-singlecore-no-nic-ddr3-llc4mb]
|
||||
agfi=agfi-07f3c2762e4349327
|
||||
agfi=agfi-0659b86373011fe04
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
||||
[firesim-quadcore-nic-ddr3-llc4mb]
|
||||
agfi=agfi-0c078780eadb4203b
|
||||
agfi=agfi-0b929d88d9f66c9f5
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
||||
[firesim-quadcore-no-nic-ddr3-llc4mb]
|
||||
agfi=agfi-0e9945a181069cc67
|
||||
agfi=agfi-0fb7f0fe1602f9cd9
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
||||
[firesim-singlecore-no-nic-lbp]
|
||||
agfi=agfi-05ca0d174e131e124
|
||||
agfi=agfi-047644ef3f61ae041
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
||||
[firesim-supernode-quadcore-nic-ddr3-llc4mb]
|
||||
agfi=agfi-012e0df3c4b90375d
|
||||
[firesim-supernode-singlecore-nic-lbp]
|
||||
agfi=agfi-0498cf07932fd2e99
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
||||
|
|
|
@ -12,3 +12,4 @@ This section describes methods of debugging the target design and the simulation
|
|||
Debugging-Hardware-Using-ILA.rst
|
||||
TracerV.rst
|
||||
DESSERT.rst
|
||||
printf-synthesis.rst
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
Printf Synthesis
|
||||
===================
|
||||
|
||||
MIDAS can synthesize printfs present in FIRRTL (implemented as ``printf``
|
||||
statements) that would otherwise be lost in the FPGA synthesis flow. Rocket and
|
||||
BOOM have printfs of their commit logs and other useful transaction
|
||||
streams.
|
||||
|
||||
::
|
||||
|
||||
C0: 409 [1] pc=[008000004c] W[r10=0000000000000000][1] R[r 0=0000000000000000] R[r20=0000000000000003] inst=[f1402573] csrr a0, mhartid
|
||||
C0: 410 [0] pc=[008000004c] W[r 0=0000000000000000][0] R[r 0=0000000000000000] R[r20=0000000000000003] inst=[f1402573] csrr a0, mhartid
|
||||
C0: 411 [0] pc=[008000004c] W[r 0=0000000000000000][0] R[r 0=0000000000000000] R[r20=0000000000000003] inst=[f1402573] csrr a0, mhartid
|
||||
C0: 412 [1] pc=[0080000050] W[r 0=0000000000000000][0] R[r10=0000000000000000] R[r 0=0000000000000000] inst=[00051063] bnez a0, pc + 0
|
||||
C0: 413 [1] pc=[0080000054] W[r 5=0000000080000054][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[00000297] auipc t0, 0x0
|
||||
C0: 414 [1] pc=[0080000058] W[r 5=0000000080000064][1] R[r 5=0000000080000054] R[r16=0000000000000003] inst=[01028293] addi t0, t0, 16
|
||||
C0: 415 [1] pc=[008000005c] W[r 0=0000000000010000][1] R[r 5=0000000080000064] R[r 5=0000000080000064] inst=[30529073] csrw mtvec, t0
|
||||
|
||||
Synthesizing these printfs lets you capture the same logs on a running FireSim instance.
|
||||
|
||||
Enabling Printf Synthesis
|
||||
----------------------------
|
||||
|
||||
To synthesize a printf, in your Chisel source you need to annotate the specific
|
||||
printfs you'd like to capture. Presently, due to a limitation in Chisel and
|
||||
FIRRTL's annotation system, you need to annotate the arguments to the printf, not the printf itself,
|
||||
like so:
|
||||
|
||||
::
|
||||
|
||||
printf(midas.targetutils.SynthesizePrintf("x%d p%d 0x%x\n", rf_waddr, rf_waddr, rf_wdata))
|
||||
|
||||
Be judicious, as synthesizing many, frequently active printfs, will slow down your simulator.
|
||||
|
||||
Once your printfs have been annotated, to enable printf synthesis add the ``WithPrintfSynthesis`` Config to your
|
||||
PLATFORM_CONFIG in SimConfigs.scala. During compilation, MIDAS will print the
|
||||
number of printfs it's synthesized. In the target's generated header
|
||||
(``<DESIGN>-const.h``), you'll find metadata for each of the printfs MIDAS synthesized.
|
||||
This is passed as argument to the constructor of the ``synthesized_prints_t``
|
||||
endpoint driver, which will be automatically instantiated in FireSim driver.
|
||||
|
||||
Runtime Arguments
|
||||
-----------------
|
||||
**+printfile**
|
||||
Specifies the file into which the synthesized printf log should written.
|
||||
|
||||
**+print-start**
|
||||
Specifies the target-cycle at which the printf trace should be captured in the
|
||||
simulator. Since capturing high-bandwidth printf traces will slow down
|
||||
simulation, this allows the user to reach the region-of-interest at full simulation speed.
|
||||
|
||||
**+print-end**
|
||||
Specifies the target cycle at which to stop pulling the synthesized print
|
||||
trace from the simulator.
|
||||
|
||||
**+print-human-readable**
|
||||
By default, a captured printf trace will be written to file as a raw,
|
||||
unformatted binary, as properly formatting the printf further slows the
|
||||
simulator. Setting this will properly format the print data before writing
|
||||
it to file.
|
||||
|
||||
Related Publications
|
||||
--------------------
|
||||
|
||||
Printf synthesis was first presented in our FPL2018 paper, `DESSERT
|
||||
<https://people.eecs.berkeley.edu/~biancolin/papers/dessert-fpl18.pdf>`_.
|
|
@ -1 +1 @@
|
|||
Subproject commit 50d4a55873741d01f9381f6fa56aa6ced2a4bb5b
|
||||
Subproject commit 71a361090c98b89455deb5fd90eba8f08b3b34e8
|
|
@ -23,12 +23,13 @@ SBT_FLAGS ?= -J-Xmx16G -J-Xss8M -J-XX:MaxPermSize=256M -J-XX:MaxMetaspaceSize=51
|
|||
firesim_base_dir := $(abspath .)
|
||||
|
||||
# Manage the FIRRTL dependency manually
|
||||
FIRRTL_JAR ?= $(firesim_base_dir)/lib/firrtl.jar
|
||||
FIRRTL_SUBMODULE_DIR ?= $(firesim_base_dir)/firrtl
|
||||
FIRRTL_JAR ?= $(FIRRTL_SUBMODULE_DIR)/utils/bin/firrtl.jar
|
||||
$(FIRRTL_JAR): $(shell find $(FIRRTL_SUBMODULE_DIR)/src/main/scala -iname "*.scala")
|
||||
$(MAKE) -C $(FIRRTL_SUBMODULE_DIR) SBT="$(SBT) $(SBT_FLAGS)" root_dir=$(FIRRTL_SUBMODULE_DIR) build-scala
|
||||
mkdir -p $(@D)
|
||||
cp -p $(FIRRTL_SUBMODULE_DIR)/utils/bin/firrtl.jar $(FIRRTL_JAR)
|
||||
touch $(FIRRTL_JAR)
|
||||
mkdir -p $(firesim_base_dir)/lib
|
||||
cp -p $(FIRRTL_JAR) $(firesim_base_dir)/lib/
|
||||
|
||||
firrtl: $(FIRRTL_JAR)
|
||||
.PHONY: firrtl
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit ba12915e9b93685107c503b3f91b96d491c48459
|
||||
Subproject commit 380c233b43c2de53b0ee15a39e9364d438066b9f
|
|
@ -1 +1 @@
|
|||
Subproject commit d9251aea8bc7c4f65ea46013e319d41cbdeb1944
|
||||
Subproject commit 12991c628ce506cf462e5c5c24688bd99c5b2b74
|
|
@ -11,6 +11,7 @@
|
|||
#include "endpoints/sim_mem.h"
|
||||
#include "endpoints/fpga_memory_model.h"
|
||||
#include "endpoints/synthesized_assertions.h"
|
||||
#include "endpoints/synthesized_prints.h"
|
||||
|
||||
firesim_top_t::firesim_top_t(int argc, char** argv)
|
||||
{
|
||||
|
@ -333,11 +334,30 @@ uint64_t host_mem_offset = -0x80000000LL;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// add more endpoints here
|
||||
// There can only be one instance of assert and print widgets as their IO is
|
||||
// uniquely generated by a FIRRTL transform
|
||||
#ifdef ASSERTIONWIDGET_struct_guard
|
||||
#ifdef ASSERTIONWIDGET_0_PRESENT
|
||||
ASSERTIONWIDGET_0_substruct_create;
|
||||
endpoints.push_back(new synthesized_assertions_t(this, ASSERTIONWIDGET_0_substruct));
|
||||
add_endpoint(new synthesized_assertions_t(this, ASSERTIONWIDGET_0_substruct));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PRINTWIDGET_struct_guard
|
||||
#ifdef PRINTWIDGET_0_PRESENT
|
||||
PRINTWIDGET_0_substruct_create;
|
||||
print_endpoint = new synthesized_prints_t(this,
|
||||
args,
|
||||
PRINTWIDGET_0_substruct,
|
||||
PRINTWIDGET_0_print_count,
|
||||
PRINTWIDGET_0_token_bytes,
|
||||
PRINTWIDGET_0_idle_cycles_mask,
|
||||
PRINTWIDGET_0_print_offsets,
|
||||
PRINTWIDGET_0_format_strings,
|
||||
PRINTWIDGET_0_argument_counts,
|
||||
PRINTWIDGET_0_argument_widths,
|
||||
PRINTWIDGET_0_DMA_ADDR);
|
||||
add_endpoint(print_endpoint);
|
||||
#endif
|
||||
#endif
|
||||
// Add functions you'd like to periodically invoke on a paused simulator here.
|
||||
|
@ -348,7 +368,7 @@ uint64_t host_mem_offset = -0x80000000LL;
|
|||
|
||||
bool firesim_top_t::simulation_complete() {
|
||||
bool is_complete = false;
|
||||
for (auto e: endpoints) {
|
||||
for (auto &e: endpoints) {
|
||||
is_complete |= e->terminate();
|
||||
}
|
||||
return is_complete;
|
||||
|
@ -362,7 +382,7 @@ uint64_t firesim_top_t::profile_models(){
|
|||
}
|
||||
|
||||
int firesim_top_t::exit_code(){
|
||||
for (auto e: endpoints) {
|
||||
for (auto &e: endpoints) {
|
||||
if (e->exit_code())
|
||||
return e->exit_code();
|
||||
}
|
||||
|
@ -371,11 +391,11 @@ int firesim_top_t::exit_code(){
|
|||
|
||||
|
||||
void firesim_top_t::run() {
|
||||
for (auto e: fpga_models) {
|
||||
for (auto &e: fpga_models) {
|
||||
e->init();
|
||||
}
|
||||
|
||||
for (auto e: endpoints) {
|
||||
for (auto &e: endpoints) {
|
||||
e->init();
|
||||
}
|
||||
|
||||
|
@ -394,7 +414,7 @@ void firesim_top_t::run() {
|
|||
run_scheduled_tasks();
|
||||
step(get_largest_stepsize(), false);
|
||||
while(!done() && !simulation_complete()){
|
||||
for (auto e: endpoints) e->tick();
|
||||
for (auto &e: endpoints) e->tick();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,5 +445,8 @@ void firesim_top_t::run() {
|
|||
for (auto e: fpga_models) {
|
||||
e->finish();
|
||||
}
|
||||
#ifdef PRINTWIDGET_0_PRESENT
|
||||
print_endpoint->finish();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
#ifndef __FIRESIM_TOP_H
|
||||
#define __FIRESIM_TOP_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "simif.h"
|
||||
#include "endpoints/endpoint.h"
|
||||
#include "endpoints/fpga_model.h"
|
||||
#include "systematic_scheduler.h"
|
||||
|
||||
#include "endpoints/synthesized_prints.h"
|
||||
|
||||
class firesim_top_t: virtual simif_t, public systematic_scheduler_t
|
||||
{
|
||||
public:
|
||||
|
@ -16,15 +20,19 @@ class firesim_top_t: virtual simif_t, public systematic_scheduler_t
|
|||
|
||||
protected:
|
||||
void add_endpoint(endpoint_t* endpoint) {
|
||||
endpoints.push_back(endpoint);
|
||||
endpoints.push_back(std::unique_ptr<endpoint_t>(endpoint));
|
||||
}
|
||||
|
||||
private:
|
||||
// Memory mapped endpoints bound to software models
|
||||
std::vector<endpoint_t*> endpoints;
|
||||
std::vector<std::unique_ptr<endpoint_t> > endpoints;
|
||||
// FPGA-hosted models with programmable registers & instrumentation
|
||||
std::vector<FpgaModel*> fpga_models;
|
||||
|
||||
#ifdef PRINTWIDGET_struct_guard
|
||||
synthesized_prints_t * print_endpoint;
|
||||
#endif
|
||||
|
||||
// profile interval: # of cycles to advance before profiling instrumentation registers in models
|
||||
uint64_t profile_interval = -1;
|
||||
uint64_t profile_models();
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
#include "Stack.h"
|
||||
#elif defined DESIGNNAME_AssertModule
|
||||
#include "AssertModule.h"
|
||||
#elif defined DESIGNNAME_PrintfModule
|
||||
#include "PrintfModule.h"
|
||||
#elif defined DESIGNNAME_NarrowPrintfModule
|
||||
#include "NarrowPrintfModule.h"
|
||||
#endif
|
||||
|
||||
class dut_emul_t:
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
//See LICENSE for license details.
|
||||
|
||||
#include "PrintfModule.h"
|
||||
class NarrowPrintfModule_t: public print_module_t, virtual simif_t
|
||||
{
|
||||
public:
|
||||
NarrowPrintfModule_t(int argc, char** argv): print_module_t(argc, argv) {};
|
||||
virtual void run() {
|
||||
print_endpoint->init();
|
||||
poke(reset, 1);
|
||||
poke(enable, 0);
|
||||
step(1);
|
||||
poke(enable, 1);
|
||||
poke(reset, 0);
|
||||
step(4);
|
||||
// Test idle-cycle rollover
|
||||
poke(enable, 0);
|
||||
step(256);
|
||||
poke(enable, 1);
|
||||
run_and_collect_prints(256);
|
||||
};
|
||||
};
|
|
@ -0,0 +1,54 @@
|
|||
//See LICENSE for license details.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "simif.h"
|
||||
#include "endpoints/synthesized_prints.h"
|
||||
|
||||
class print_module_t: virtual simif_t
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<synthesized_prints_t> print_endpoint;
|
||||
print_module_t(int argc, char** argv) {
|
||||
PRINTWIDGET_0_substruct_create;
|
||||
std::vector<std::string> args(argv + 1, argv + argc);
|
||||
print_endpoint = std::unique_ptr<synthesized_prints_t>(new synthesized_prints_t(this,
|
||||
args,
|
||||
PRINTWIDGET_0_substruct,
|
||||
PRINTWIDGET_0_print_count,
|
||||
PRINTWIDGET_0_token_bytes,
|
||||
PRINTWIDGET_0_idle_cycles_mask,
|
||||
PRINTWIDGET_0_print_offsets,
|
||||
PRINTWIDGET_0_format_strings,
|
||||
PRINTWIDGET_0_argument_counts,
|
||||
PRINTWIDGET_0_argument_widths,
|
||||
PRINTWIDGET_0_DMA_ADDR));
|
||||
};
|
||||
void run_and_collect_prints(int cycles) {
|
||||
step(cycles, false);
|
||||
while (!done()) {
|
||||
print_endpoint->tick();
|
||||
}
|
||||
print_endpoint->finish();
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef DESIGNNAME_PrintfModule
|
||||
class PrintfModule_t: public print_module_t, virtual simif_t
|
||||
{
|
||||
public:
|
||||
PrintfModule_t(int argc, char** argv): print_module_t(argc, argv) {};
|
||||
virtual void run() {
|
||||
print_endpoint->init();
|
||||
poke(reset, 1);
|
||||
poke(a, 0);
|
||||
poke(b, 0);
|
||||
step(1);
|
||||
poke(reset, 0);
|
||||
step(1);
|
||||
poke(a, 1);
|
||||
poke(b, 1);
|
||||
run_and_collect_prints(256);
|
||||
};
|
||||
};
|
||||
#endif //DESIGNNAME_PrintfModule
|
|
@ -34,7 +34,7 @@ driver_dir = $(firesim_base_dir)/src/main/cc
|
|||
DRIVER_H = $(shell find $(driver_dir) -name "*.h")
|
||||
DRIVER_CC := $(driver_dir)/midasexamples/Driver.cc
|
||||
|
||||
TARGET_CXX_FLAGS := -DDESIGNDRIVERCLASS=$(DESIGN)_t -DDESIGNNAME_$(DESIGN) -I$(driver_dir) -I$(driver_dir)/midasexamples
|
||||
TARGET_CXX_FLAGS := -DDESIGNDRIVERCLASS=$(DESIGN)_t -DDESIGNNAME_$(DESIGN) -I$(driver_dir) -I$(driver_dir)/midasexamples -g
|
||||
TARGET_LD_FLAGS :=
|
||||
|
||||
##########################
|
||||
|
|
|
@ -31,6 +31,12 @@ class WithSynthAsserts extends Config((site, here, up) => {
|
|||
case EndpointKey => EndpointMap(Seq(new midas.widgets.AssertBundleEndpoint)) ++ up(EndpointKey)
|
||||
})
|
||||
|
||||
// Experimental: mixing this in will enable print synthesis
|
||||
class WithPrintfSynthesis extends Config((site, here, up) => {
|
||||
case midas.SynthPrints => true
|
||||
case EndpointKey => EndpointMap(Seq(new midas.widgets.PrintRecordEndpoint)) ++ up(EndpointKey)
|
||||
})
|
||||
|
||||
class WithSerialWidget extends Config((site, here, up) => {
|
||||
case EndpointKey => up(EndpointKey) ++ EndpointMap(Seq(new SimSerialIO))
|
||||
})
|
||||
|
|
|
@ -10,6 +10,7 @@ import junctions._
|
|||
// This is incomplete and must be mixed into a complete platform config
|
||||
class DefaultMIDASConfig extends Config(new Config((site, here, up) => {
|
||||
case SynthAsserts => true
|
||||
case SynthPrints => true
|
||||
}) ++ new Config(new firesim.firesim.WithDefaultMemModel))
|
||||
|
||||
class PointerChaserConfig extends Config((site, here, up) => {
|
||||
|
|
|
@ -18,7 +18,7 @@ trait GeneratorUtils {
|
|||
Class.forName(s"firesim.midasexamples.${targetName}")
|
||||
.getConstructors.head
|
||||
.newInstance()
|
||||
.asInstanceOf[chisel3.Module]
|
||||
.asInstanceOf[chisel3.experimental.RawModule]
|
||||
}
|
||||
def midasParams = (platform match {
|
||||
case midas.F1 => new Config(new DefaultMIDASConfig ++ new midas.F1Config)
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
//See LICENSE for license details.
|
||||
|
||||
package firesim.midasexamples
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.LFSR16
|
||||
import chisel3.experimental.MultiIOModule
|
||||
|
||||
import midas.targetutils.SynthesizePrintf
|
||||
|
||||
class PrintfModule extends MultiIOModule {
|
||||
val a = IO(Input(Bool()))
|
||||
val b = IO(Input(Bool()))
|
||||
|
||||
val cycle = RegInit(0.U(16.W))
|
||||
|
||||
when(a) { cycle := cycle + 1.U }
|
||||
|
||||
// Printf format strings must be prefixed with "SYNTHESIZED_PRINT CYCLE: %d"
|
||||
// so they can be pulled out of RTL simulators log and sorted within a cycle
|
||||
// As the printf order will be different betwen RTL simulator and synthesized stream
|
||||
printf(SynthesizePrintf("SYNTHESIZED_PRINT CYCLE: %d\n", cycle))
|
||||
|
||||
val wideArgument = VecInit(Seq.fill(33)(WireInit(cycle))).asUInt
|
||||
printf(SynthesizePrintf("SYNTHESIZED_PRINT CYCLE: %d wideArgument: %x\n", cycle, wideArgument)) // argument width > DMA width
|
||||
|
||||
val childInst = Module(new PrintfModuleChild)
|
||||
childInst.c := a
|
||||
childInst.cycle := cycle
|
||||
|
||||
printf(SynthesizePrintf("thi$!sn+taS/\neName", "SYNTHESIZED_PRINT CYCLE: %d constantArgument: %x\n", cycle, 1.U(8.W)))
|
||||
}
|
||||
|
||||
class PrintfModuleChild extends MultiIOModule {
|
||||
val c = IO(Input(Bool()))
|
||||
val cycle = IO(Input(UInt(16.W)))
|
||||
|
||||
val lfsr = chisel3.util.LFSR16(c)
|
||||
printf(SynthesizePrintf("SYNTHESIZED_PRINT CYCLE: %d LFSR: %x\n", cycle, lfsr))
|
||||
|
||||
//when (lsfr(0)) {
|
||||
// printf(SynthesizePrintf(p"SYNTHESIZED_PRINT CYCLE: ${cycle} LFSR is odd"))
|
||||
//}
|
||||
}
|
||||
|
||||
class NarrowPrintfModule extends MultiIOModule {
|
||||
val enable = IO(Input(Bool()))
|
||||
val cycle = RegInit(0.U(12.W))
|
||||
cycle := cycle + 1.U
|
||||
when(LFSR16()(0) & LFSR16()(0) & enable) {
|
||||
printf(SynthesizePrintf("SYNTHESIZED_PRINT CYCLE: %d\n", cycle(5,0)))
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package firesim.midasexamples
|
|||
|
||||
import java.io.File
|
||||
import scala.sys.process.{stringSeqToProcess, ProcessLogger}
|
||||
import scala.io.Source
|
||||
|
||||
abstract class TutorialSuite(
|
||||
val targetName: String, // See GeneratorUtils
|
||||
|
@ -69,6 +70,26 @@ abstract class TutorialSuite(
|
|||
ignore should s"pass in ${testEnv}" in { }
|
||||
}
|
||||
}
|
||||
|
||||
// Checks that the synthesized print log in ${genDir}/${synthPrintLog} matches the
|
||||
// printfs from the RTL simulator
|
||||
def diffSynthesizedPrints(synthPrintLog: String) {
|
||||
behavior of "synthesized print log"
|
||||
it should "match the logs produced by the verilated design" in {
|
||||
def printLines(filename: File): Seq[String] = {
|
||||
val lines = Source.fromFile(filename).getLines.toList
|
||||
lines.filter(_.startsWith("SYNTHESIZED_PRINT")).sorted
|
||||
}
|
||||
|
||||
val verilatedOutput = printLines(new File(outDir, s"/${targetName}.verilator.out"))
|
||||
val synthPrintOutput = printLines(new File(genDir, s"/${synthPrintLog}"))
|
||||
assert(verilatedOutput.size == synthPrintOutput.size && verilatedOutput.nonEmpty)
|
||||
for ( (vPrint, sPrint) <- verilatedOutput.zip(synthPrintOutput) ) {
|
||||
assert(vPrint == sPrint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clean
|
||||
mkdirs
|
||||
compile
|
||||
|
@ -90,3 +111,11 @@ class StackF1Test extends TutorialSuite("Stack", midas.F1, 8)
|
|||
class RiscF1Test extends TutorialSuite("Risc", midas.F1, 64)
|
||||
class RiscSRAMF1Test extends TutorialSuite("RiscSRAM", midas.F1, 64)
|
||||
class AssertModuleF1Test extends TutorialSuite("AssertModule", midas.F1)
|
||||
class PrintfModuleF1Test extends TutorialSuite("PrintfModule", midas.F1,
|
||||
simulationArgs = Seq("+print-human-readable", "+printfile=synthprinttest.out")) {
|
||||
diffSynthesizedPrints("synthprinttest.out")
|
||||
}
|
||||
class NarrowPrintfModuleF1Test extends TutorialSuite("NarrowPrintfModule", midas.F1,
|
||||
simulationArgs = Seq("+print-human-readable", "+printfile=synthprinttest.out")) {
|
||||
diffSynthesizedPrints("synthprinttest.out")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue