Package: pf-dev-tools
pfDevToolsA collection of tools forProject Freedomprojects.Copyright (c) 2023-presentDidier Malenfant.InstallationpfDevToolsworks onmacOS,LinuxandWindows.You can installpfDevToolsby typing the following in a terminal window:pip install pf-dev-toolsPre-requisitespfDevToolsrequires at leastPython3.10. Make sure you have at leastPython3.10 before proceeding.It also uses thegitcommand. If you're onmacOSandLinuxthis should come already built in.By default,pfDevToolsuses a local/native install of theQuartustoolchain to build bitstream files on your machine. You just need to make sure thatquartus_shis in yourPATH.SinceQuartusis only available onWindowsorLinux, ifquartus_shis not found on your system the toolchain will switch to usingdockerinstead. To usedocker, you'll need to installDocker Desktopand to make sure theDocker Engineis running while building the core. On anApple SiliconMac, make sure thatUse Virtualization frameworkandUse Rosetta for x86/amd64 emulation on Apple Siliconare both enabled indocker'sSettings->General.By default a docker image forQartus22.1 will be used. If you want to use a different version ofQuartus, you can definePF_DOCKER_IMAGE_NAMEin your environment (i.e.export PF_DOCKER_IMAGE_NAME=didiermalenfant/quartus:22.1-apple-silicon) to point to a different docker image to use.pfCommandpfDevTools's main functionality is centered around thepfcommand. It provides tools used for buildingopenFPGAcores and will also eventually be used to buildpfxroms.Usage:pf <options> command <arguments>The following options are supported:--help/-h                             - Show a help message.
  --version/-v                          - Display the app's version.
  --debug/-d                            - Enable extra debugging information.cleancommandpf cleanCleans the project and deletes any intermediate build files. This should be executed in the same folder as the project'sSConstructfile.This should be executed in the same folder as the project'sSConstructfile.clonecommandpf clone <url> <tag=name> dest_folderClones the repo found aturl, optionally at a given tag/branch namednameinto the folderdest_folder. 'url' does not need to be pre-fixed withhttps://or post-fixed with.git.Ifurlis missing thencodeberg.org/DidierMalenfant/pfCoreTemplateis used.convertcommandpf convert src_filename dest_filenameConverts an image to the openFGPA binary format used for core images and author icons.deletecommandpf delete core_name <volume_path>Deletes all core data (bitstream, images, icons, json files) for core namedcore_nameon volume at <volume_path>.Ifvolume_pathis omitted then the command looks for thePF_CORE_INSTALL_PATHenvironment variable. If this is not defined either then it defaults to/Volumes/POCKETonmacOS,/media/<username>/POCKETonlinuxor theP:drive onWindows(learn how to set the drive letterhere).If another implementation of the core is found then the Platforms files will be kept otherwise they are deleted too.dryruncommandpf dryrunSimulate building the project. This will give out information on what, if anything, needs to be rebuilt.This should be executed in the same folder as the project'sSConstructfile.ejectcommandpf eject <volume_path>Ejects the volume atvolumePath.Ifvolume_pathis omitted then the command looks for thePF_CORE_INSTALL_PATHenvironment variable. If this is not defined either then it defaults to/Volumes/POCKETonmacOS,/media/<username>/POCKETonlinuxor theP:drive onWindows(learn how to set the drive letterhere).installcommandpf install <--no_build> <--eject>)pf install <--eject> zip_file <volume_path>If no zip file is specified then this will build the project and installs it to where thePF_CORE_INSTALL_PATHenvironment variable points to. Using--no_buildwill skip trying to build the project before installing it.This should be executed in the same folder as the project'sSConstructfile.If a zip file is specified this this will install the packaged core contained inzip_fileonto volume atvolume_path. Ifvolume_pathis omitted then the command looks for thePF_CORE_INSTALL_PATHenvironment variable.For both options, using--ejectwill eject the volume after a successful install and ifPF_CORE_INSTALL_PATHis not defined either then it defaults to/Volumes/POCKETonmacOS,/media/<username>/POCKETonlinuxor theP:drive onWindows(learn how to set the drive letterhere).makecommandpf makeBuilds the local project.This should be executed in the same folder as the project'sSConstructfile.programcommandpf programBuild the project and program theAnalogue Pocket FPGAcore via aJTAGblaster cable. You will need a core to be currently running on thePocketin order to use this. Because theFPGAis then reprogrammed without going through thePocket's interface, the video scaler will retain whatever scaling settings were set by the previous core. This may cause the display to be incorrectly scaled if the settings are different for the new core.This is currently only supported onlinuxandWindowsand requires a local/native install of theQuartustool chain with thequartus_pgmin yourPATH.This should be executed in the same folder as the project'sSConstructfile.qfscommandpf qfs qsf_file <cpus=num> files...Edits aQuartusqfsproject file to add files and set number of cpu for the project. Updates theqfs_fileby adding a list ofVerilog.vor.svfiles, separated by spaces.Optionallycpuscan set the number of cpu cores that the compilation process can use.reversecommandpf reverse src_filename dest_filenameReverses the bitstream file atsrc_filenameand writes it todest_filename.Building an openFPGA corepfDevToolsprovides an entire toolchain needed to compileopenFPGAcores. The build systems is based on theSConssoftware construction tool which is entirely written inPython.A typical makefile is namedSConstructand foropenFPGAprojects can look as simple as this:importpfDevTools# -- We need pf-dev-tools version 1.x.x but at least 1.0.5.pfDevTools.requires('1.0.5')env=pfDevTools.SConsEnvironment()env.OpenFPGACore('src/config.toml')This will build, usingpf make, a packaged core file based on thetomlconfigfileand the source code found in thesrcfolder.All projects should contain at least onecore/core_top.vfile at the root of their source tree. The content of this file should be based aroundAnalogue's owncore.top.vfilebut you do not need to provide any other files orIPfound in thecore template. Those will be automatically brought in for you during the build.Good examples of simple core projects can be found in the examples provided as part of theopenFPGA tutorials.The build environment can be customized by passing variables to thepfDevTools.SConsEnvironment()method call like so:env=pfDevTools.SConsEnvironment(PF_BUILD_FOLDER='MyBuildFolder',PF_SRC_FOLDER='MySrcFolder')The following variables are currently supported:PF_SRC_FOLDER- Root folder for all theVerilogsource files for the project. Defaults to the folder where thetomlconfig [file]](#core-config-file-format) is located.PF_BUILD_FOLDER- Folder where intermediate build files are created. Defaults to_build.PF_CORE_TEMPLATE_REPO_URL- Repo url to use instead of the default core template repo atcodeberg.org/DidierMalenfant/pfCoreTemplate.PF_CORE_TEMPLATE_REPO_TAG- Repo tag to use to clone the core template repo.PF_CORE_TEMPLATE_REPO_FOLDER- Path to a local core template folder to copy instead of cloning a repo.'PF_NB_OF_CPUS_TO_USE' - Number of cpu cores that the compilation process can use in parallel.'PF_ENABLE_OPTIMIZATION' - If set to 1 then the core will be compiled usingHIGH PERFORMANCE EFFORT.Core config file formatCore configuration is done via a singletomlfile, passed as an argument toenv.OpenFPGACore. This file is split into various sections:[Platform]sectionThis section is used to provide information about the platform your core is implementing:name(string): Name of the platform, as displayed in the Pocket's menus. Maximum length is 31 characters.category(string): Category this platform belongs to. Maximum length is 31 characters.short_name(string): Short name for the platform. This is used for paths in the SD card's filesystem. Maximum length is 31 characters.image(path): Path to a 521x165graphic fileassociated with the platform. Can be a 'png' or 'jpeg' file which will be automatically converted to the format expected by the console.description(string): Short description. Maximum length is 63 characters.info(path): Path, relative to the config file's folder, to a text file containing extra information that will be shown in the core’sPlatform Detailview. Up to 32 lines can be displayed. No special characters. Bullet points can be shown by starting a line with an*.For example:[Platform]
name = "pfx-1"
image = "assets/pfx1-platform-image.png"
short_name = "pfx1"
category = "Fantasy"
description = "An open-source fantasy gaming console for the Analog Pocket."
info = "info.txt"[Build]sectionThis section contains information about the given build of the core:version(string): Version of the release.SemVeris highly encouraged. Maximum length is 31 characters.For example:[Build]
version = "0.0.1"[Author]sectionThis section contains information about the author of the core:name(string): Name of the core author. Maximum length is 31 characters.icon(path): Path, relative to the config file's folder, to a 36x36graphic fileassociated with the author. Can be a 'png' or 'jpeg' file which will be automatically converted to the format expected by the console.url(string): URL to more information about core. Maximum length is 63 characters.For example:[Author]
name = "dm"
icon = "assets/pfx1-core-author-icon.png"
url = "https://codeberg.org/DidierMalenfant/-/projects/6314"[Hardware]sectionThis section contains configuration parameters for theAnalogue Pocket's hardware:video_width(unsigned integer): Width of the screen in pixels.video_height(unsigned integer): Height of the screen in pixels.video_rotation_angle(unsigned integer): Rotation in degrees to apply to the screen. Supported values are0,90,180or270(Optional: Defaults to0).video_flip_horizontal(boolean): Flip/mirror the screen horizontally (Optional: Defaults tofalse).video_flip_vertical(boolean): Flip/mirror the screen vertically (Optional: Defaults tofalse).power_cartridge_port(boolean): Provide power to the cartridge port (Optional: Defaults tofalse).For example:[Hardware]
video_width = 400
video_height = 360
video_rotation_angle = 0
video_flip_horizontal = false
video_flip_vertical = false
power_cartridge_port = true[Cores]sectionIn the vast majority of cases, you should not need to define a[Cores]section in your configuration, the default values should work fine. But if your platform provides multiple cores like, for example, one for NTSC resolution and one for PAL then you will need to specify those cores manually.The[Cores]section is made of up to 8[Cores.<id>]sections. Each section contains configuration parameters for one core:id(16-bit unsigned integer): Identification number for the core. (Optional: If no cores are specified in the config file then this defaults to0).name(string): Name of the core. Maximum length is 15 characters (Optional: Defaults todefault).source_file(string): Source bitstream file to use for the core. This is assumed to be located in the core template'soutput_filesfolder (Optional: Defaults topf_core.rbf).filename(string): Filename for the reverse bitstream file packaged with the core. Maximum length is 15 characters  (Optional: Defaults tobitstream.rbf_r).For example, not specifying any[Cores]section is the same as:[Cores]
  [Cores.0]
  name = "default"
  source_file = "pf_core.rbf"
  filename = "bitstream.rbf_r"[Files]sectionThe[Files]section is made of up to 32[Files.<id>]sections. Each section contains configuration parameters for one file:id(16-bit unsigned integer): Identification number for the file.name(string): User-facing name of the file. Maximum length is 15 characters.required(boolean): Iftruethe file will be requested from the user in a dialog, otherwise it will be skipped (Optional: Defaults totrue).defer_loading(boolean): Iftrue, file will not be loaded, but its size and ID will still be communicated to the core, and the core may read from or write to it (Optional: Defaults tofalse).secondary(boolean): Iftrue, file will be ignored, and will only be loaded if referenced in a selected variant/instance (Optional: Defaults tofalse).non_volatile(boolean): Iftrue, file will be both loaded and unloaded on core exit allowing modifications to remain between separate core launches (Optional: Defaults tofalse).parameters(list of strings): Some parameters to apply to this file (Optional: Defaults to no parameters). Supported parameters are:user-reloadable: The file is reloadable. An entry namedLoad <name>is added in the core settings.core-specific: File is specific only to this core, instead of all the cores for this platform.non-volatile-filename: The filename to use is one cloned from file0with this file's extension appended.read-only: File is read-only and cannot be modified.instance-json: Treat a JSON loaded as this file as an instance description. Must also be flagged ascore-specific, and only valid for the first file.init-non-volatile-data-on-load: If no file is loaded on init, the file's memory is overwritten with0xFFup tomaximum_size.reset-core-while-loading:Reset Entercommand will be sent before executing theData Slot Request WriteandData Slot Access All CompletethenReset Exitwill be sent after.restart-core-after-loading: Entire core is unloaded via the normal process, saving any non-volatile files. Then a full restart of the core is done, using the new data along with other already-defined assets.full-reload-core: Same as above, but the bitstream is also reloaded before the restart process.persist-browsed-filename: Filenames picked via the browser will be persisted, and the next time the file is loaded, the same choice will be used, overriding any definition or instance filename. The browser cache, which is saved per-core, is cleared when a user usesReset All to Defaultsin the core'sInteractmenu.extensions(list of string): Array of up to 4 supported file extensions. Each extension may be up to 7 characters.required_size(32-bit unsigned integer or hex string with 0x prefix): Exact size required for the file (Optional: Defaults to no required size).maximum_size(32-bit unsigned integer or hex string with 0x prefix_): Maximum size allowed for the file (Optional: Defaults to no maximum size).address(32-bit unsigned integer or hex string with 0x prefix): Address that will be used to access the file via the BRIDGE interface.include_files(list of file paths): List of paths, relative to the config file's folder, for all the files that should be packaged with the core. All files end up in the same folder so each filename must be unique. Maximum filename length is 31 characters (Optional: Defaults to no files included).For example:[Files]
  [Files.1]
  name = "Background"
  required = true
  parameters = [ "user-reloadable", "core-specific" ]
  extensions = [ "bin" ]
  required_size = 184320
  address = "0x00000000"
  include_files = [ "assets/images/ex_image_1.bin", "assets/images/ex_image_2.bin", "assets/images/ex_image_3.bin" ][Variables]sectionThe[Variables]section is made of up to 16 variables[Variables.<id>]sections. Variables are user-facing in theCore Settingsmenu and enable the user to pass configuration settings onto the core. Each section contains configuration parameters for one variable:id(16-bit unsigned integer): Identification number for the variable.name(string): User-facing name of the variable. Maximum length is 15 characters.type(string): Type of variable. Should be eitherradio_button,checkbox,slider,list,numberoraction.enabled(boolean): Whether the variable is enabled or not (Optional: Defaults totrue).address(32-bit unsigned integer or hex string): Address that will be used to access the variable via the BRIDGE interface.Some parameters apply only toradio_buttonvariables:group(32-bit unsigned integer or hex string): Group identifier. Buttons with the same group will be grouped together.persistent(boolean): Retains the value set by the user after the core is shut own (Optional: Defaults tofalse).write-only(boolean): Iftruevalue will never be read back from the core. (Optional: Defaults tofalse).default(boolean): Default state of the button, on or off.value_on(32-bit unsigned integer or hex string): Value written when the button is on.value_off(32-bit unsigned integer or hex string): Value written when the button is on (Optional: Defaults to0).mask(32-bit unsigned integer or hex string): Bits set to1will be left untouched when writing a value. Bits set to0may be modified by the UI element (Optional: Defaults to0)Some parameters apply only tocheckboxvariables:persistent(boolean): Retains the value set by the user after the core is shut own (Optional: Defaults tofalse).write-only(boolean): Iftruevalue will never be read back from the core (Optional: Defaults tofalse).default(boolean): Default state of the checkbox, on or off.value_on(32-bit unsigned integer or hex string): Value written when the box is checked.value_off(32-bit unsigned integer or hex string): Value written when the box is checked (Optional: Defaults to0).mask(32-bit unsigned integer or hex string): Bits set to1will be left untouched when writing a value. Bits set to0may be modified by the UI element (Optional: Defaults to0)Some parameters apply only toslidervariables:persistent(boolean): Retains the value set by the user after the core is shut own (Optional: Defaults tofalse).write-only(boolean): Iftruevalue will never be read back from the core (Optional: Defaults tofalse).default(32-bit integer or hex string): Default value/position of the slider.mask(32-bit integer or hex string): Bits set to1will be left untouched when writing a value. Bits set to ‘0may be modified by the UI element (**Optional**: Defaults to0`)signed_value(boolean): Indicates whether the value displayed should be treated os signed or unsigned (Optional: Defaults tofalse).minimum_value(32-bit integer or hex string): Minimum value the slider can be set to.maximum_value(32-bit integer or hex string): Maximum value the slider can be set to.small_step(32-bit unsigned integer or hex string): Smallest increment the slider can move.large_step(32-bit unsigned integer or hex string): Largest increment the slider can move.Some parameters apply only tolistvariables:choices(List ofname/valuepairs): Up to 16 choices for the list using the following pairs:name(string): Name of the choice. Maximum length is 23 characters.value(32-bit integer or hex string): Value that is written when making that choice.mask(32-bit unsigned integer or hex string): Bits set to1will be left untouched when writing a value. Bits set to0may be modified by the UI element (Optional: Defaults to0)Some parameters apply only toactionvariables:value(32-bit integer or hex string): Value that is written when the action is selected.mask(32-bit unsigned integer or hex string): Bits set to1will be left untouched when writing a value. Bits set to0may be modified by the UI element (Optional: Defaults to0)For example:[Variables]
  [Variables.1]
  name = "Screen Border"
  type = "checkbox"
  persistent = true
  address = "0x50000000"
  default = true
  value_on = 23
  mask = "0xFFFF0000"[Controllers]sectionThe[Variables]section is made of up to 4 variables[Controllers.<id>]sections. EachControllercontains information on how to map keys to actions in your core. User can then remap these action in theControlsmenu of the core settings. The following parameters are supported:id(16-bit unsigned integer): Identification number for the controller.key_mapping(List ofname/key_codepairs):name(string): Name of the action. Maximum length is 19 characters.key_code(string): Key this action is mapped to by default. This can be any of the following:A,B,X,Y,L,R,StartorSelect.For example:[Controllers]
  [Controllers.1]
  key_mapping = [ [ "Purple Square", "A" ],
                  [ "Green Square", "B" ],
                  [ "Replay Audio", "X" ] ]Installing Docker on Ubuntu LinuxMake sure that no other version ofDockerare installed:sudo apt-get remove docker docker-engine docker.io containerd runcAdd the docker repository:sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/nullInstall theDocker Engine:sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginIn order to be able to rundockerwithoutsudo, make sure thedockergroup exists and add your user to it:sudo groupadd docker
sudo usermod -aG docker $USER
newgrp dockerYou can verify that theDocker Engineinstallation is successful by running thehello-worldimage:docker run hello-worldAssigning a drive letter to a volume on WindowsBy defaultpf-dev-toolsuses theP:(for Pocket) drive onWindowsfor installing cores. You can set your SD card to use the same drive letter by doing the following:Right-click on theStartbutton.ClickDisk Managementto open theDisk Managementconsole.Right-click the volume that has the drive letter you want to change.ClickChange Drive Letter And Paths.TrademarksopenFPGAand theopenFPGAlogo are trademarks ofAnalogueEnterprises Ltd.Quartusis a registered trademark ofIntel.This project is not affiliated, associated with, sponsored or supported by neitherAnaloguenorIntel.LicensepfDevToolsis distributed under the terms of theGPLv3.0or later license.