Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Creating a New Physical Device
Physical devices are those latency-insensitive modules which, in addition to having latency-insensitive channel I/O also have physical wires, typically to an external chip. There are two methods of incorporating a new device into LEAP: the old "physical platform" method and the new, experimental "user-level device" method.
At its lowest level, LEAP views the FPGA as a collection of physical device: PCI-e, DDR, SERDES, RF, etc.
An example "physical platform":https://github.com/LEAP-Core/leap-platforms/tree/master/modules/bluespec/common/fpgaenv/physical-platform/pci-express-generic is shown here:
// PHYSICAL_DRIVERS // This represents the collection of all platform capabilities which the // rest of the FPGA uses to interact with the outside world. // We use other modules to actually do the work. interface PHYSICAL_DRIVERS; interface CLOCKS_DRIVER clocksDriver; interface PCIE_DRIVER pcieDriver; interface DDR_DRIVER ddrDriver; interface AURORA_COMPLEX_DRIVERS auroraDriver; endinterface // TOP_LEVEL_WIRES // The TOP_LEVEL_WIRES is the datatype which gets passed to the top level // and output as input/output wires. These wires are then connected to // physical pins on the FPGA as specified in the accompanying UCF file. // These wires are defined in the individual devices. interface TOP_LEVEL_WIRES; // wires from devices interface CLOCKS_WIRES clocksWires; interface PCIE_WIRES pcieWires; interface DDR_WIRES ddrWires; interface AURORA_COMPLEX_WIRES auroraWires; endinterface // PHYSICAL_PLATFORM // The platform is the aggregation of wires and drivers. interface PHYSICAL_PLATFORM; interface PHYSICAL_DRIVERS physicalDrivers; interface TOP_LEVEL_WIRES topLevelWires; endinterface // mkPhysicalPlatform // This is a convenient way for the outside world to instantiate all the devices // and an aggregation of all the wires. module [CONNECTED_MODULE] mkPhysicalPlatform //interface: (PHYSICAL_PLATFORM); // The Platform is instantiated inside a NULL clock domain. Our first course of // action should be to instantiate the Clocks Physical Device and obtain interfaces // to clock and reset the other devices with. CLOCKS_DEVICE clocks <- mkClocksDevice(); Clock clk = clocks.driver.clock; Reset rst = clocks.driver.reset; // There is a strong assumption that the clock for this module is the 200MHz // differential clock. let ddrConfig = defaultValue; ddrConfig.internalClock = clocks.driver.rawClock; ddrConfig.internalReset = clocks.driver.rawReset; ddrConfig.modelResetNeedsFanout = True; case (\`DRAM_CLOCK_MECHANISM) matches "InternalUnbuffered": ddrConfig.clockArchitecture = CLOCK_INTERNAL_UNBUFFERED; "ExternalDifferential": ddrConfig.clockArchitecture = CLOCK_EXTERNAL_DIFFERENTIAL; default: ddrConfig.clockArchitecture = CLOCK_INTERNAL_BUFFERED; endcase // Set the ddr clock source by parameter. DDR_DEVICE sdram <- mkDDRDevice(ddrConfig, clocked_by clk, reset_by clocks.driver.baseReset); // Next, create the physical device that can trigger a soft reset. Pass along the // interface to the trigger module that the clocks device has given us. let pcieRst <- mkResetFanout(clocks.driver.baseReset, clocked_by clk); PCIE_DEVICE pcie <- mkPCIEDevice(clocks.driver.rawClock, clocks.driver.rawReset, clocked_by clk, reset_by pcieRst); // // Pass reset from PCIe to the model. The host holds reset long enough that // a crossing wire to the model clock domain is sufficient. // Reg#(Bool) pcieInReset <- mkReg(True, clocked_by pcie.driver.clock, reset_by pcie.driver.reset); ReadOnly#(Bool) assertModelReset <- mkNullCrossingWire(clocks.driver.clock, pcieInReset, clocked_by pcie.driver.clock, reset_by pcie.driver.reset); (* fire_when_enabled, no_implicit_conditions *) rule exitResetPCIe (pcieInReset); pcieInReset <= False; endrule (* fire_when_enabled *) rule triggerModelReset (assertModelReset); clocks.softResetTrigger.reset(); endrule AURORA_COMPLEX aurora_device <- mkAuroraDevice(clocks.driver.rawClock, clocks.driver.rawReset, clocked_by clk, reset_by rst); // // Aggregate the drivers // interface PHYSICAL_DRIVERS physicalDrivers; interface clocksDriver = clocks.driver; interface pcieDriver = pcie.driver; interface ddrDriver = sdram.driver; interface auroraDriver = aurora_device.drivers; endinterface // // Aggregate the wires // interface TOP_LEVEL_WIRES topLevelWires; interface clocksWires = clocks.wires; interface pcieWires = pcie.wires; interface ddrWires = sdram.wires; interface auroraWires = aurora_device.wires; endinterface endmodule