Merge remote-tracking branch 'origin/dev' into eliminate-macros

This commit is contained in:
Sagar Karandikar 2018-11-06 22:49:20 +00:00
commit f50e7812b0
20 changed files with 201 additions and 84 deletions

View File

@ -254,6 +254,7 @@ class FireSimServerNode(FireSimNode):
all_paths.append(self.server_hardware_config.get_local_driver_path())
all_paths.append(self.server_hardware_config.get_local_runtime_conf_path())
all_paths.append(self.server_hardware_config.get_local_assert_def_path())
return all_paths
def get_agfi(self):

View File

@ -17,6 +17,7 @@ from runtools.run_farm import RunFarm
from util.streamlogger import StreamLogger
LOCAL_DRIVERS_BASE = "../sim/output/f1/"
LOCAL_DRIVERS_GENERATED_SRC = "../sim/generated-src/f1/"
CUSTOM_RUNTIMECONFS_BASE = "../sim/custom-runtime-configs/"
rootLogger = logging.getLogger()
@ -44,12 +45,15 @@ class RuntimeHWConfig:
rootLogger.debug("Setting deploytriplet by querying the AGFI's description.")
self.deploytriplet = get_firesim_tagval_for_agfi(self.agfi,
'firesim-deploytriplet')
def get_design_name(self):
""" Returns the name used to prefix MIDAS-emitted files. (The DESIGN make var) """
my_deploytriplet = self.get_deploytriplet_for_config()
my_design = my_deploytriplet.split("-")[0]
return my_design
def get_local_driver_binaryname(self):
""" Get the name of the driver binary. """
my_deploytriplet = self.get_deploytriplet_for_config()
my_design = my_deploytriplet.split("-")[0]
return my_design + "-f1"
return self.get_design_name() + "-f1"
def get_local_driver_path(self):
""" return relative local path of the driver used to run this sim. """
@ -73,6 +77,13 @@ class RuntimeHWConfig:
runtime_conf_local = CUSTOM_RUNTIMECONFS_BASE + my_runtimeconfig
return runtime_conf_local
# TODO: Delete this and bake the assertion definitions into the Driver
def get_local_assert_def_path(self):
""" return relative local path of the synthesized assertion definitions. """
my_deploytriplet = self.get_deploytriplet_for_config()
gen_src_dir = LOCAL_DRIVERS_GENERATED_SRC + "/" + my_deploytriplet + "/"
assert_def_local = gen_src_dir + self.get_design_name() + ".asserts"
return assert_def_local
def get_boot_simulation_command(self, macaddr, blkdev, slotid,
linklatency, netbw, profile_interval, bootbin,

View File

@ -10,27 +10,27 @@
# own images.
[fireboom-singlecore-nic-ddr3-llc4mb]
agfi=agfi-0f49cce505a37bb66
agfi=agfi-081263395d71230d0
deploytripletoverride=None
customruntimeconfig=None
[fireboom-singlecore-no-nic-ddr3-llc4mb]
agfi=agfi-0e367b373ad68241e
agfi=agfi-02ca50cd6abf64276
deploytripletoverride=None
customruntimeconfig=None
[firesim-quadcore-nic-ddr3-llc4mb]
agfi=agfi-05d1fffbd3a3d7ca1
agfi=agfi-03516efc65833f8b8
deploytripletoverride=None
customruntimeconfig=None
[firesim-quadcore-no-nic-ddr3-llc4mb]
agfi=agfi-06ed3210fd5fd2d13
agfi=agfi-0c038cf7eed4dddf0
deploytripletoverride=None
customruntimeconfig=None
[firesim-singlecore-no-nic-lbp]
agfi=agfi-0b3d4bd1ec8599f4c
agfi=agfi-013ba1560c665ff23
deploytripletoverride=None
customruntimeconfig=None

View File

@ -0,0 +1,43 @@
Assertion Synthesis
===================
MIDAS can synthesize assertions present in FIRRTL (implemented as ``stop``
statements) that would otherwise be lost in the FPGA synthesis flow. Rocket
and BOOM include hundreds of such assertions which, when synthesized, can
provide great insight into why the target may be failing.
Enabling Assertion Synthesis
----------------------------
To enable assertion synthesis add the ``WithSynthAsserts`` Config to your
PLATFORM_CONFIG in SimConfigs.scala. During compilation, MIDAS will print the
number of assertions it's synthesized. In the target's ``generated-src/``
directory, you'll find a ``*.asserts`` file with the definitions of all
synthesized assertions. If assertion synthesis has been enabled, the
``synthesized_assertions_t`` endpoint driver will be automatically instantiated
the driver.
Runtime Behavior
----------------
If an assertion is caught during simulation, the driver will print the
assertion cause, the path to module instance in which it fired, a source
locator, and the cycle on which the assertion fired. Simulation will then
terminate.
An example of an assertion caught in a dual-core instance of BOOM is given
below:
::
id: 1190, module: IssueSlot_4, path: FireBoomNoNIC.tile_1.core.issue_units_0.slots_3]
Assertion failed
at issue_slot.scala:214 assert (!slot_p1_poisoned)
at cycle: 2142042185
Related Publications
--------------------
Assertion synthesis was first presented in our FPL2018 paper, `DESSERT
<https://people.eecs.berkeley.edu/~biancolin/papers/dessert-fpl18.pdf>`_.

View File

@ -1,5 +1,5 @@
Debugging Using FPGA Integrated Logic Analyzers (ILA)
=======================================
=====================================================
Sometimes it takes too long to simulate FireSim on RTL simulators, and
in some occasions we would also like to debug the simulation infrastructure

View File

@ -11,3 +11,4 @@ This section describes methods of debugging the target design and the simulation
RTL-Simulation.rst
Debugging-Hardware-Using-ILA.rst
TracerV.rst
DESSERT.rst

View File

@ -2,7 +2,7 @@ FireSim Asked Questions
=============================
I just bumped the FireSim repository to a newer commit and simulations aren't running. What is going on?
----------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------
Anytime there is an AGFI bump, FireSim simulations will break/hang due to outdated AFGI. To get the new default AGFI's you must run the manager initialization again by doing the following:

@ -1 +1 @@
Subproject commit 95b7c49b2a54801207538ec7658bd3902750c36b
Subproject commit 3519ef0de53decdf8602dd4433a39bc49c98923f

View File

@ -10,6 +10,7 @@
#include "endpoints/fpga_model.h"
#include "endpoints/sim_mem.h"
#include "endpoints/fpga_memory_model.h"
#include "endpoints/synthesized_assertions.h"
firesim_top_t::firesim_top_t(int argc, char** argv)
{
@ -131,6 +132,9 @@ firesim_top_t::firesim_top_t(int argc, char** argv)
// add more endpoints here
#ifdef ASSERTIONWIDGET_0
endpoints.push_back(new synthesized_assertions_t(this));
#endif
// Add functions you'd like to periodically invoke on a paused simulator here.
if (profile_interval != -1) {
register_task([this](){ return this->profile_models();}, 0);

View File

@ -0,0 +1,43 @@
//See LICENSE for license details.
#include "simif.h"
#include "endpoints/synthesized_assertions.h"
class AssertModule_t: virtual simif_t
{
public:
synthesized_assertions_t * assert_endpoint;
AssertModule_t(int argc, char** argv) { assert_endpoint = new synthesized_assertions_t(this); };
void run() {
int assertions_thrown = 0;
poke(reset, 1);
poke(io_a, 0);
poke(io_b, 0);
poke(io_c, 0);
step(1);
poke(reset, 0);
step(1);
poke(io_cycleToFail, 1024);
poke(io_a, 1);
step(4096, false);
while (!done()) {
assert_endpoint->tick();
if (assert_endpoint->terminate()) {
if (assertions_thrown == 0) {
poke(io_cycleToFail, 2048);
poke(io_b, 1);
poke(io_a, 0);
} else if (assertions_thrown == 1) {
poke(io_cycleToFail, 3056);
poke(io_b, 0);
poke(io_c, 1);
} else {
poke(io_c, 0);
}
assert_endpoint->resume();
assertions_thrown++;
}
}
expect(assertions_thrown == 3, "EXPECT: Three assertions thrown");
};
};

View File

@ -25,6 +25,8 @@
#include "ShiftRegister.h"
#elif defined DESIGNNAME_Stack
#include "Stack.h"
#elif defined DESIGNNAME_AssertModule
#include "AssertModule.h"
#endif
class dut_emul_t:

View File

@ -18,59 +18,6 @@ import junctions.{NastiIO, NastiKey}
case object LoopbackNIC extends Field[Boolean]
class BRAMFlowQueue[T <: Data](val entries: Int)(data: => T) extends Module {
val io = IO(new QueueIO(data, entries))
require(entries > 1)
io.count := 0.U
val do_flow = Wire(Bool())
val do_enq = io.enq.fire() && !do_flow
val do_deq = io.deq.fire() && !do_flow
val maybe_full = RegInit(false.B)
val enq_ptr = Counter(do_enq, entries)._1
val (deq_ptr, deq_done) = Counter(do_deq, entries)
when (do_enq =/= do_deq) { maybe_full := do_enq }
val ptr_match = enq_ptr === deq_ptr
val empty = ptr_match && !maybe_full
val full = ptr_match && maybe_full
val atLeastTwo = full || enq_ptr - deq_ptr >= 2.U
do_flow := empty && io.deq.ready
val ram = Mem(entries, data)
when (do_enq) { ram.write(enq_ptr, io.enq.bits) }
val ren = io.deq.ready && (atLeastTwo || !io.deq.valid && !empty)
val raddr = Mux(io.deq.valid, Mux(deq_done, 0.U, deq_ptr + 1.U), deq_ptr)
val ram_out_valid = RegNext(ren)
io.deq.valid := Mux(empty, io.enq.valid, ram_out_valid)
io.enq.ready := !full
io.deq.bits := Mux(empty, io.enq.bits, RegEnable(ram.read(raddr), ren))
}
class BRAMQueue[T <: Data](val entries: Int)(data: => T) extends Module {
val io = IO(new QueueIO(data, entries))
io.count := 0.U
val fq = Module(new BRAMFlowQueue(entries)(data))
fq.io.enq <> io.enq
io.deq <> Queue(fq.io.deq, 1, pipe = true)
}
object BRAMQueue {
def apply[T <: Data](enq: DecoupledIO[T], entries: Int) = {
val q = Module((new BRAMQueue(entries)) { enq.bits })
q.io.enq.valid := enq.valid // not using <> so that override is allowed
q.io.enq.bits := enq.bits
enq.ready := q.io.enq.ready
q.io.deq
}
}
class SplitSeqQueue(implicit p: Parameters) extends Module {
/* hacks. the version of FIRRTL we're using can't handle >= 512-bit-wide
stuff. there are a variety of reasons to not fix it this way, but I just

View File

@ -97,7 +97,7 @@ trait HasFireSimGeneratorUtilities extends HasGeneratorUtilities with HasTestSui
val portList = target.getPorts flatMap {
case Port(id: DebugIO, _) => None
case Port(id: AutoBundle, _) => None // What the hell is AutoBundle?
case otherPort => Some(otherPort.id)
case otherPort => Some(otherPort.id.instanceName -> otherPort.id)
}
generatorArgs.midasFlowKind match {

View File

@ -20,6 +20,12 @@ class BasePlatformConfig extends Config(new Config((site, here, up) => {
case EndpointKey => EndpointMap(Seq.empty)
}) ++ new midas.F1Config)
// Experimental: mixing this in will enable assertion synthesis
class WithSynthAsserts extends Config((site, here, up) => {
case midas.SynthAsserts => true
case EndpointKey => EndpointMap(Seq(new midas.widgets.AssertBundleEndpoint)) ++ up(EndpointKey)
})
class WithSerialWidget extends Config((site, here, up) => {
case EndpointKey => up(EndpointKey) ++ EndpointMap(Seq(new SimSerialIO))
})

View File

@ -32,16 +32,10 @@ class WithNICKey extends Config((site, here, up) => {
ctrlQueueDepth = 64)
})
class WithLargeTLBs extends Config((site, here, up) => {
class WithRocketL2TLBs(entries: Int) extends Config((site, here, up) => {
case RocketTilesKey => up(RocketTilesKey) map (tile => tile.copy(
icache = tile.icache map (_.copy(
nTLBEntries = 32 // TLB reach = 32 * 4KB = 128KB
)),
dcache = tile.dcache map (_.copy(
nTLBEntries = 32 // TLB reach = 32 * 4KB = 128KB
)),
core = tile.core.copy(
nL2TLBEntries = 1024 // TLB reach = 1024 * 4KB = 4MB
nL2TLBEntries = entries
)
))
})
@ -52,11 +46,9 @@ class WithPerfCounters extends Config((site, here, up) => {
))
})
class BoomWithLargeTLBs extends Config((site, here, up) => {
class WithBoomL2TLBs(entries: Int) extends Config((site, here, up) => {
case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(
core = tile.core.copy(
nL2TLBEntries = 1024 // TLB reach = 1024 * 4KB = 4MB
)
core = tile.core.copy(nL2TLBEntries = entries)
))
})
@ -68,6 +60,14 @@ class WithTraceBoom extends Config((site, here, up) => {
case BoomTilesKey => up(BoomTilesKey, site) map { r => r.copy(trace = true) }
})
// This is strictly speakig a MIDAS config, but it's target dependent -> mix in to target config
class WithBoomSynthAssertExcludes extends Config((site, here, up) => {
case midas.ExcludeInstanceAsserts => Seq(
// Boom instantiates duplicates of these module(s) with the expectation
// the backend tool will optimize them away. FIXME.
("NonBlockingDCache", "dtlb"))
})
/*******************************************************************************
* Full TARGET_CONFIG configurations. These set parameters of the target being
* simulated.
@ -86,10 +86,14 @@ class FireSimRocketChipConfig extends Config(
new WithUARTKey ++
new WithNICKey ++
new WithBlockDevice ++
new WithLargeTLBs ++
new WithRocketL2TLBs(1024) ++
new WithPerfCounters ++
new freechips.rocketchip.system.DefaultConfig)
class WithNDuplicatedRocketCores(n: Int) extends Config((site, here, up) => {
case RocketTilesKey => List.tabulate(n)(i => up(RocketTilesKey).head.copy(hartId = i))
})
class FireSimRocketChipTracedConfig extends Config(
new WithTraceRocket ++ new FireSimRocketChipConfig)
@ -101,7 +105,7 @@ class FireSimRocketChipSingleCoreTracedConfig extends Config(
// dual core config
class FireSimRocketChipDualCoreConfig extends Config(
new WithNBigCores(2) ++
new WithNDuplicatedRocketCores(2) ++
new FireSimRocketChipSingleCoreConfig)
class FireSimRocketChipDualCoreTracedConfig extends Config(
@ -109,7 +113,7 @@ class FireSimRocketChipDualCoreTracedConfig extends Config(
// quad core config
class FireSimRocketChipQuadCoreConfig extends Config(
new WithNBigCores(4) ++
new WithNDuplicatedRocketCores(4) ++
new FireSimRocketChipSingleCoreConfig)
class FireSimRocketChipQuadCoreTracedConfig extends Config(
@ -117,7 +121,7 @@ class FireSimRocketChipQuadCoreTracedConfig extends Config(
// hexa core config
class FireSimRocketChipHexaCoreConfig extends Config(
new WithNBigCores(6) ++
new WithNDuplicatedRocketCores(6) ++
new FireSimRocketChipSingleCoreConfig)
class FireSimRocketChipHexaCoreTracedConfig extends Config(
@ -125,7 +129,7 @@ class FireSimRocketChipHexaCoreTracedConfig extends Config(
// octa core config
class FireSimRocketChipOctaCoreConfig extends Config(
new WithNBigCores(8) ++
new WithNDuplicatedRocketCores(8) ++
new FireSimRocketChipSingleCoreConfig)
class FireSimRocketChipOctaCoreTracedConfig extends Config(
@ -139,9 +143,22 @@ class FireSimBoomConfig extends Config(
new WithUARTKey ++
new WithNICKey ++
new WithBlockDevice ++
new BoomWithLargeTLBs ++
new WithBoomL2TLBs(1024) ++
new WithBoomSynthAssertExcludes ++ // Will do nothing unless assertion synth is enabled
// Using a small config because it has 64-bit system bus, and compiles quickly
new boom.system.SmallBoomConfig)
// A safer implementation than the one in BOOM in that it
// duplicates whatever BOOMTileKey.head is present N times. This prevents
// accidentally (and silently) blowing away configurations that may change the
// tile in the "up" view
class WithNDuplicatedBoomCores(n: Int) extends Config((site, here, up) => {
case BoomTilesKey => List.tabulate(n)(i => up(BoomTilesKey).head.copy(hartId = i))
})
class FireSimBoomDualCoreConfig extends Config(
new WithNDuplicatedBoomCores(2) ++
new FireSimBoomConfig)
class FireSimBoomTracedConfig extends Config(
new WithTraceBoom ++ new FireSimBoomConfig)

View File

@ -0,0 +1,32 @@
//See LICENSE for license details.
package firesim.midasexamples
import chisel3._
class ChildModule extends Module {
val io = IO(new Bundle {
val pred = Input(Bool())
})
assert(!io.pred, "Pred asserted")
}
class AssertModule extends Module {
val io = IO(new Bundle {
val cycleToFail = Input(UInt(16.W))
val a = Input(Bool())
val b = Input(Bool())
val c = Input(Bool())
})
val cycle = RegInit(0.U(16.W))
cycle := cycle + 1.U
assert(io.cycleToFail =/= cycle || !io.a, "A asserted")
when (io.cycleToFail === cycle) {
assert(!io.b, "B asserted")
}
val cMod = Module(new ChildModule)
cMod.io.pred := io.c && io.cycleToFail === cycle
}

View File

@ -7,6 +7,11 @@ import midas.widgets._
import freechips.rocketchip.config._
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
}) ++ new Config(new firesim.firesim.WithDefaultMemModel))
class PointerChaserConfig extends Config((site, here, up) => {
case MemSize => BigInt(1 << 30) // 1 GB
case NMemoryChannels => 1

View File

@ -20,4 +20,8 @@ class GCD extends Module {
when (io.e) { x := io.a; y := io.b }
io.z := x
io.v := y === 0.U
assert(!io.e || io.a =/= 0.U && io.b =/= 0.U, "Inputs to GCD cannot be 0")
printf("X: %d, Y:%d\n", x, y)
}

View File

@ -21,7 +21,7 @@ trait GeneratorUtils {
.asInstanceOf[chisel3.Module]
}
def midasParams = (platform match {
case midas.F1 => new Config(new firesim.firesim.WithDefaultMemModel ++ new midas.F1Config)
case midas.F1 => new Config(new DefaultMIDASConfig ++ new midas.F1Config)
}).toInstance
lazy val hostTransforms = Seq(

View File

@ -89,3 +89,4 @@ class EnableShiftRegisterF1Test extends TutorialSuite("EnableShiftRegister", mid
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)