diff --git a/sim/firesim-lib/src/main/cc/bridges/serial.cc b/sim/firesim-lib/src/main/cc/bridges/serial.cc index 3fa08ab8..1d8aeae1 100644 --- a/sim/firesim-lib/src/main/cc/bridges/serial.cc +++ b/sim/firesim-lib/src/main/cc/bridges/serial.cc @@ -4,8 +4,8 @@ #include #include "serial.h" -serial_t::serial_t(simif_t* sim, const std::vector& args, SERIALBRIDGEMODULE_struct * mmio_addrs, int serialno, int64_t mem_host_offset): - bridge_driver_t(sim), sim(sim), mem_host_offset(mem_host_offset) { +serial_t::serial_t(simif_t* sim, const std::vector& args, SERIALBRIDGEMODULE_struct * mmio_addrs, int serialno, bool has_mem, int64_t mem_host_offset): + bridge_driver_t(sim), sim(sim), has_mem(has_mem), mem_host_offset(mem_host_offset) { this->mmio_addrs = mmio_addrs; @@ -56,7 +56,7 @@ serial_t::serial_t(simif_t* sim, const std::vector& args, SERIALBRI printf("\n"); std::vector args_new(argv_arr, argv_arr + argc_count); - fesvr = new firesim_fesvr_t(args_new); + fesvr = new firesim_fesvr_t(args_new, has_mem); } serial_t::~serial_t() { @@ -89,6 +89,7 @@ void serial_t::recv() { void serial_t::handle_loadmem_read(fesvr_loadmem_t loadmem) { assert(loadmem.size % sizeof(uint32_t) == 0); + assert(has_mem); // Loadmem reads are in granularities of the width of the FPGA-DRAM bus mpz_t buf; mpz_init(buf); @@ -118,6 +119,7 @@ void serial_t::handle_loadmem_read(fesvr_loadmem_t loadmem) { void serial_t::handle_loadmem_write(fesvr_loadmem_t loadmem) { assert(loadmem.size <= 1024); + assert(has_mem); static char buf[1024]; fesvr->recv_loadmem_data(buf, loadmem.size); mpz_t data; diff --git a/sim/firesim-lib/src/main/cc/bridges/serial.h b/sim/firesim-lib/src/main/cc/bridges/serial.h index 55f50bdf..05d0035e 100644 --- a/sim/firesim-lib/src/main/cc/bridges/serial.h +++ b/sim/firesim-lib/src/main/cc/bridges/serial.h @@ -29,13 +29,14 @@ struct serial_data_t { args, \ SERIALBRIDGEMODULE_ ## IDX ## _substruct, \ IDX, \ + SERIALBRIDGEMODULE_ ## IDX ## _has_memory, \ SERIALBRIDGEMODULE_ ## IDX ## _memory_offset)); \ #ifdef SERIALBRIDGEMODULE_struct_guard class serial_t: public bridge_driver_t { public: - serial_t(simif_t* sim, const std::vector& args, SERIALBRIDGEMODULE_struct * mmio_addrs, int serialno, int64_t mem_host_offset); + serial_t(simif_t* sim, const std::vector& args, SERIALBRIDGEMODULE_struct * mmio_addrs, int serialno, bool has_mem, int64_t mem_host_offset); ~serial_t(); virtual void init(); virtual void tick(); @@ -47,6 +48,7 @@ class serial_t: public bridge_driver_t SERIALBRIDGEMODULE_struct * mmio_addrs; simif_t* sim; firesim_fesvr_t* fesvr; + bool has_mem; // host memory offset based on the number of memory models and their size int64_t mem_host_offset; // Number of target cycles between fesvr interactions diff --git a/sim/firesim-lib/src/main/cc/fesvr/firesim_fesvr.cc b/sim/firesim-lib/src/main/cc/fesvr/firesim_fesvr.cc index 826655a1..ae2e1669 100644 --- a/sim/firesim-lib/src/main/cc/fesvr/firesim_fesvr.cc +++ b/sim/firesim-lib/src/main/cc/fesvr/firesim_fesvr.cc @@ -16,7 +16,7 @@ int firesim_fesvr_t::host_thread(void *arg) return 0; } -firesim_fesvr_t::firesim_fesvr_t(const std::vector args) : htif_t(args) +firesim_fesvr_t::firesim_fesvr_t(const std::vector args, bool has_loadmem) : htif_t(args), has_loadmem(has_loadmem) { is_loadmem = false; is_busy = false; diff --git a/sim/firesim-lib/src/main/cc/fesvr/firesim_fesvr.h b/sim/firesim-lib/src/main/cc/fesvr/firesim_fesvr.h index a0e22206..104b9eb8 100644 --- a/sim/firesim-lib/src/main/cc/fesvr/firesim_fesvr.h +++ b/sim/firesim-lib/src/main/cc/fesvr/firesim_fesvr.h @@ -26,7 +26,7 @@ struct fesvr_loadmem_t { class firesim_fesvr_t : public htif_t { public: - firesim_fesvr_t(const std::vector args); + firesim_fesvr_t(const std::vector args, bool has_loadmem); ~firesim_fesvr_t(){}; bool busy() { return is_busy; } bool data_available(); @@ -44,7 +44,7 @@ class firesim_fesvr_t : public htif_t void reset(); void load_program() { wait(); // Switch back to commit all pending requests - is_loadmem = true; + is_loadmem = has_loadmem; htif_t::load_program(); is_loadmem = false; } @@ -65,6 +65,7 @@ class firesim_fesvr_t : public htif_t private: bool is_busy; + bool has_loadmem; // A flag set only during program load to forward fesvr // read/write_chunks to the loadmem unit instead of going over tsi bool is_loadmem; diff --git a/sim/firesim-lib/src/main/scala/bridges/SerialBridge.scala b/sim/firesim-lib/src/main/scala/bridges/SerialBridge.scala index dbd4f6bb..5df302b2 100644 --- a/sim/firesim-lib/src/main/scala/bridges/SerialBridge.scala +++ b/sim/firesim-lib/src/main/scala/bridges/SerialBridge.scala @@ -10,16 +10,26 @@ import freechips.rocketchip.config.Parameters import testchipip.{SerialIO, SerialAdapter} -class SerialBridge(memoryRegionName: String) extends BlackBox with Bridge[HostPortIO[SerialBridgeTargetIO], SerialBridgeModule] { +/** + * Class which parameterizes the SerialBridge + * + * memoryRegionNameOpt, if unset, indicates that firesim-fesvr should not attempt to write a payload into DRAM through the loadmem unit. + * This is suitable for target designs which do not use the FASED DRAM model. + * If a FASEDBridge for the backing AXI4 memory is present, then memoryRegionNameOpt should be set to the same memory region name which is passed + * to the FASEDBridge. This enables fast payload loading in firesim-fesvr through the loadmem unit. + */ +case class SerialBridgeParams(memoryRegionNameOpt: Option[String]) + +class SerialBridge(memoryRegionNameOpt: Option[String]) extends BlackBox with Bridge[HostPortIO[SerialBridgeTargetIO], SerialBridgeModule] { val io = IO(new SerialBridgeTargetIO) val bridgeIO = HostPort(io) - val constructorArg = Some(memoryRegionName) + val constructorArg = Some(SerialBridgeParams(memoryRegionNameOpt)) generateAnnotations() } object SerialBridge { - def apply(clock: Clock, port: SerialIO, memoryRegionName: String)(implicit p: Parameters): SerialBridge = { - val ep = Module(new SerialBridge(memoryRegionName)) + def apply(clock: Clock, port: SerialIO, memoryRegionNameOpt: Option[String])(implicit p: Parameters): SerialBridge = { + val ep = Module(new SerialBridge(memoryRegionNameOpt)) ep.io.serial <> port ep.io.clock := clock ep @@ -32,8 +42,8 @@ class SerialBridgeTargetIO extends Bundle { val clock = Input(Clock()) } -class SerialBridgeModule(val memoryRegionName: String)(implicit p: Parameters) - extends BridgeModule[HostPortIO[SerialBridgeTargetIO]]()(p) with HostDramHeaderConsts { +class SerialBridgeModule(serialBridgeParams: SerialBridgeParams)(implicit p: Parameters) + extends BridgeModule[HostPortIO[SerialBridgeTargetIO]]()(p) { lazy val module = new BridgeModuleImp(this) { val io = IO(new WidgetIO) val hPort = IO(HostPort(new SerialBridgeTargetIO)) @@ -83,6 +93,9 @@ class SerialBridgeModule(val memoryRegionName: String)(implicit p: Parameters) import CppGenerationUtils._ val headerWidgetName = getWName.toUpperCase super.genHeader(base, sb) + val memoryRegionNameOpt = serialBridgeParams.memoryRegionNameOpt + val offsetConstName = memoryRegionNameOpt.map(GetMemoryRegionOffsetConstName(_)).getOrElse("0") + sb.append(genMacro(s"${headerWidgetName}_has_memory", memoryRegionNameOpt.isDefined.toString)) sb.append(genMacro(s"${headerWidgetName}_memory_offset", offsetConstName)) } } diff --git a/sim/midas/src/main/scala/midas/platform/PlatformShim.scala b/sim/midas/src/main/scala/midas/platform/PlatformShim.scala index 80bfaab8..56c2f071 100644 --- a/sim/midas/src/main/scala/midas/platform/PlatformShim.scala +++ b/sim/midas/src/main/scala/midas/platform/PlatformShim.scala @@ -37,6 +37,7 @@ abstract class PlatformShim(implicit p: Parameters) extends LazyModule()(p) { val top = LazyModule(new midas.core.FPGATop) def genHeader(sb: StringBuilder, target: String) { sb.append("#include \n") + sb.append("#include \n") sb.append(genStatic("TARGET_NAME", CStrLit(target))) sb.append(genMacro("PLATFORM_TYPE", s"V${this.getClass.getSimpleName}")) sb.append(genMacro("data_t", "uint32_t")) diff --git a/sim/midas/src/main/scala/midas/widgets/UsesHostDRAM.scala b/sim/midas/src/main/scala/midas/widgets/UsesHostDRAM.scala index 8e4a4516..1bfa83a8 100644 --- a/sim/midas/src/main/scala/midas/widgets/UsesHostDRAM.scala +++ b/sim/midas/src/main/scala/midas/widgets/UsesHostDRAM.scala @@ -35,6 +35,10 @@ import chisel3.util.isPow2 */ case class MemorySlaveConstraints(address: Seq[AddressSet], supportsRead: TransferSizes, supportsWrite: TransferSizes) +object GetMemoryRegionOffsetConstName { + def apply(memoryRegionName: String) = s"${memoryRegionName}_offset" +} + /** * A common trait for referring collateral in the generated header. * @@ -50,7 +54,7 @@ trait HostDramHeaderConsts { * */ def memoryRegionName: String - def offsetConstName = s"${memoryRegionName}_offset" + def offsetConstName = GetMemoryRegionOffsetConstName(memoryRegionName) } /** diff --git a/target-design/chipyard b/target-design/chipyard index b76972d3..b057cfbd 160000 --- a/target-design/chipyard +++ b/target-design/chipyard @@ -1 +1 @@ -Subproject commit b76972d34b685a95fc130ad213fd19e23074fd4d +Subproject commit b057cfbd8c0560fb82cdad63a228c7b827c09bd7