From 1e241956ec2ba7989a8b248c204aedc5a14f29df Mon Sep 17 00:00:00 2001 From: Avimitin Date: Mon, 20 Jan 2025 12:35:17 +0800 Subject: [PATCH] [docker] add document to docker container Signed-off-by: Avimitin --- nix/t1/release/default.nix | 106 -------------------------- nix/t1/release/doc.nix | 28 +++++++ nix/t1/release/doc.typ | 113 ++++++++++++++-------------- nix/t1/release/docker-image.nix | 13 +++- nix/t1/release/template.typ | 128 ++++++++++++++++++++++++++++++++ 5 files changed, 224 insertions(+), 164 deletions(-) delete mode 100644 nix/t1/release/default.nix create mode 100644 nix/t1/release/doc.nix create mode 100644 nix/t1/release/template.typ diff --git a/nix/t1/release/default.nix b/nix/t1/release/default.nix deleted file mode 100644 index 1e693272c..000000000 --- a/nix/t1/release/default.nix +++ /dev/null @@ -1,106 +0,0 @@ -{ lib -, newScope - -, stdenvNoCC -, fetchFromGitHub -, runCommand -, makeWrapper -, typst -, jq - -, configName -, t1-helper -, ip -, cases -, elaborateConfigJson -, elaborateConfig -}: - -let - extension = lib.head elaborateConfig.parameter.extensions; - isFp = lib.hasInfix "f" extension; - - # dontFixup is set to true by default for debugging. However it will bring LLVM runtime and clang into the final images. - # For docker release, test ELF is for demo usage only, so I don't want those implicit huge dependencies get into the container. - stripCase = case: case.overrideAttrs { - dontFixup = false; - }; -in - -lib.makeScope newScope (scope: rec { - inherit elaborateConfigJson configName; - - testCases = map stripCase (with cases; [ - intrinsic.matmul - ] ++ lib.optionals isFp [ - intrinsic.softmax - intrinsic.linear_normalization - ]); - - emulator-wrapped = runCommand "ip-emulator" - { - nativeBuildInputs = [ makeWrapper ]; - } - '' - mkdir -p $out/bin - - makeWrapper ${t1-helper}/bin/t1-helper $out/bin/ip-emulator \ - --add-flags "t1emu" \ - --add-flags "--config ${elaborateConfigJson}" \ - --add-flags "--emulator-path ${ip.emu}/bin/emulator" - - makeWrapper ${t1-helper}/bin/t1-helper $out/bin/ip-emulator-trace \ - --add-flags "t1emu" \ - --add-flags "--config ${elaborateConfigJson}" \ - --add-flags "--trace" \ - --add-flags "--emulator-path ${ip.emu-trace}/bin/emulator" - ''; - - docker-image = scope.callPackage ./docker-image.nix { }; - - doc = stdenvNoCC.mkDerivation { - name = "${configName}-typst-release-doc"; - - nativeBuildInputs = [ typst jq ]; - - src = ./doc.typ; - - unpackPhase = - let - typstPkgs = [ - { - pkgName = "preview/codly"; - version = "0.2.0"; - src = fetchFromGitHub { - owner = "Dherse"; - repo = "codly"; - rev = "0037b522957de3ab8e88cb689bf813aafa96a1b8"; - hash = "sha256-OZB9D0KpS9qVIU6O62uPQzQKx0xFxm8/nnkFU4MIkqY="; - }; - } - ]; - in - '' - export XDG_CACHE_HOME=$(mktemp -d) - typstPkgRoot="$XDG_CACHE_HOME"/typst/packages - - ${lib.concatMapStringsSep "\n" - (info: '' - dstDir="$typstPkgRoot/${info.pkgName}/${info.version}" - mkdir -p $dstDir - cp -vrT ${info.src} "$dstDir" - '') - typstPkgs} - ls -al $typstPkgRoot - ''; - - buildPhase = '' - cp -v ${./doc.typ} ./doc.typ - jq '.name = "${configName}"' ${elaborateConfigJson} > config.json - - mkdir $out - typst compile \ - ./doc.typ $out/${configName}.pdf - ''; - }; -}) diff --git a/nix/t1/release/doc.nix b/nix/t1/release/doc.nix new file mode 100644 index 000000000..ae6a2af61 --- /dev/null +++ b/nix/t1/release/doc.nix @@ -0,0 +1,28 @@ +{ lib +, stdenvNoCC +, typst +, pandoc +}: +stdenvNoCC.mkDerivation { + name = "t1-docker-manual"; + + nativeBuildInputs = [ typst pandoc ]; + + src = with lib.fileset; toSource { + root = ./.; + fileset = unions [ + ./doc.typ + ./template.typ + ]; + }; + + buildPhase = '' + runHook preBuild + + mkdir $out + typst compile ./doc.typ $out/manual.pdf + pandoc -f typst -t markdown ./doc.typ -o $out/manual.md + + runHook postBuild + ''; +} diff --git a/nix/t1/release/doc.typ b/nix/t1/release/doc.typ index 11057f0b5..dbb5c9272 100644 --- a/nix/t1/release/doc.typ +++ b/nix/t1/release/doc.typ @@ -1,71 +1,70 @@ -#import "@preview/codly:0.2.0": * -#show: codly-init.with() -#codly(languages: ( - bash: (name: "Bash", icon: none, color: rgb("#CE412B")), -)) - -#let config = json("./config.json") - -= T1 Docker Image Manual - -== Released IP configs - -#{ - let name = config.name - let param = config.parameter - let floatSupport = if param.extensions.first() == "Zve32f" [ True ] else [ False ] - let VRFRamType = param.vrfRamType.split(".").last() - let VRF = [#param.vrfBankSize Bank, #VRFRamType] - let lsuBankCnt = param.lsuBankParameters.len() - let beatByteCnt = param.lsuBankParameters.first().beatbyte - table( - columns: 6, - [*Config Name*], [*DLEN*], [*VLEN*], [*Float support*], [*VRF*], [*LSU*], - [*#name*], [#param.dLen], [#param.vLen], [#floatSupport], [#VRF], [#lsuBankCnt bank, #beatByteCnt beatbyte], - ) -} - -== Address Range +#import "template.typ": project -#table( - columns: 3, - [*Range*], [*Usage*], [*Address Range*], - [0-1G], [Scalar Bank], [0x20000000], - [1-3G], [DDR Bank (512M/bank)], [0x40000000], - [3G-3G+2M], [SRAM Bank (256K/bank 8Banks)], [0xc0000000] +#show: project.with( + title: "T1 docker manual", ) -Scalar core cannot access Vector DDR/SRAM, for, users need to access corresponding memory banks via vector load store instructions. += Using the Emulator with Docker +The emulator environment provides a set of tools and examples to help users get +started. Below are detailed instructions and explanations for compiling and +running test cases. -== How to use the Docker image +== Examples +There are four sample source code files located in the /workspace/examples +directory. The T1 runtime stubs are placed under /workspace/share. -#show raw.where(lang: "t1-docker"): it => { - raw(lang: "bash", it.text.replace("${config}", config.name)) -} -```t1-docker -# Load the image into docker registry -docker pull ghcr.io/chipsalliance/t1-${config}:latest -# Start the bash shell in t1/release:latest image, and bind the current path to /workspace -docker run --name t1 -it -v $PWD:/workspace --rm ghcr.io/chipsalliance/t1-${config}:latest /bin/bash +This Docker container includes a Clang wrapper that simplifies the compilation +process by handling most compiler options. Users can easily compile the example +source code using the following commands: + +```bash +cd /workspace/intrinsic.linear_normalization +t1-cc -T /workspace/share/t1.ld /workspace/share/main.S linear_normalization.c -o linear_normalization.elf +t1emu-verilated-simulator +t1_elf_file=linear_normalization.elf ``` -> It is recommended to build ELF outside of the docker image and bind mount the ELF location into the image. +== Marking Memory Regions +The t1.ld file specifies how the linker organizes the memory layout. We use the following memory configurations: -== What is inside +- *Scalar memory*: Starts at 0x20000000 with a size of 512MB. +- *Vector memory*: Starts at 0x60000000 with a size of 1024MB. -+ IP emulator: `/bin/ip-emulator` -+ IP emulator with trace functionality: `/bin/ip-emulator-trace` -+ Softmax & Linear Normalization & Matmul test cases: `/workspace/cases` +Developers can use the `__attribute((section(".vbss")))` attribute to mark +regions of memory that need to be copied to SRAM. For example, in +linear_normalization.c: -== How to run some workload using IP emulator +```c +#define ARRAY_ZIZE 1024 +__attribute((section(".vbss"))) float actual[ARRAY_ZIZE]; +``` -```bash -# There are three cases under the /workspace/cases directory -ls /workspace/cases +== Main Function +The main.S file acts as the main function. It initializes all registers before +running a test case and then jumps to the test symbol. Developers writing new +test cases should use the following structure for their entry point: -# Choose one of the case to run -ip-emulator --case cases/intrinsic-matmul/bin/intrinsic.matmul.elf +```c +int test() { + // Test implementation +} +``` -# Get waveform trace file -ip-emulator-trace --case cases/intrinsic-linear_normalization/bin/intrinsic.linear_normalization.elf +== Clang Wrapper +The `t1-cc` command wraps several Clang options for convenience: + +```bash +riscv32-none-elf-clang \ + -I/path/to/t1-runtime/include -L/path/to/t1-runtime/lib \ + -mabi=ilp32f -march=rv32gc_zvl2048b_zve32f -mno-relax -static -mcmodel=medany \ + -fvisibility=hidden -fno-PIC -g -O3 -frandom-seed= ``` + +== Simulator Variants +The simulator binary may differ based on the container used: + +- Containers with the suffix *t1rocketemu* include the t1rocketemu-verilated-simulator, which uses the Rocket core. +- Containers with the suffix *t1emu* include the t1emu-verilated-simulator, which handles scalar instructions using Spike. + +*Note*: MMIO (Memory-Mapped I/O) support is currently unavailable in containers +suffixed with -t1emu. Consequently, features like printf or framebuffer will +not work in these containers. diff --git a/nix/t1/release/docker-image.nix b/nix/t1/release/docker-image.nix index 4c91e7bdf..d61a66fee 100644 --- a/nix/t1/release/docker-image.nix +++ b/nix/t1/release/docker-image.nix @@ -22,6 +22,11 @@ , xz , file + # Doc deps +, stdenvNoCC +, typst +, pandoc + # T1 Stuff , rv32-stdenv , emurt @@ -74,6 +79,10 @@ let makeWrapper ${rv32-stdenv.cc}/bin/${rv32-stdenv.targetPlatform.config}-c++ $out/bin/t1-c++ \ --set "NIX_CFLAGS_COMPILE_${cc-prefix-safe}" "$NIX_CFLAGS_COMPILE" ''; + + manual = (import ./doc.nix) { + inherit lib typst pandoc stdenvNoCC; + }; in dockerTools.streamLayeredImage { @@ -122,6 +131,8 @@ dockerTools.streamLayeredImage { mkdir -p /workspace/share cp ${../../../tests/t1.ld} /workspace/share/t1.ld cp ${../../../tests/t1_main.S} /workspace/share/main.S + + cp ${manual}/manual.md /workspace/readme.md ''; config = { @@ -129,6 +140,6 @@ dockerTools.streamLayeredImage { }; passthru = { - inherit t1-cc; + inherit t1-cc manual; }; } diff --git a/nix/t1/release/template.typ b/nix/t1/release/template.typ new file mode 100644 index 000000000..307030e35 --- /dev/null +++ b/nix/t1/release/template.typ @@ -0,0 +1,128 @@ +// Credits: https://github.com/DawnEver/mcm-icm-typst-template + +#let fontsize = 12pt +#let title-fontsize = 16pt +#let fonttype = "Times New Roman" + +// Solution to problem in first-line-indent. Please refer to https://github.com/typst/typst/issues/311#issuecomment-1556115270 +#let first-line-indent = 20pt + +#let cover( + body, + title: "", + )={ + // dividing line + pad(left:-first-line-indent)[#line(length: 100%, stroke: black)] + + // Title row. + align( + center, + )[ + #block(text(title, size: 24pt), below: 20pt, above: 20pt) + #block(text("Summary", size: title-fontsize, weight: "bold"), below: 20pt, above: 20pt) + ] + + set par( + // first-line-indent: first-line-indent, + hanging-indent: -first-line-indent, + linebreaks: "optimized", + ) + + body +} + +#let project( + title: "", + body, +) = { + // Set the document's basic properties. + set document(title: title) + set page(margin: (left: 80pt, right: 50pt, top: 40pt, bottom: 40pt)) + + set text(font: fonttype, size: fontsize) + + // Configure equation numbering and spacing. + set math.equation(numbering: "(1)", supplement: []) + show math.equation: set block(spacing: 0.65em) + + // Configure figures and tables. + set figure(supplement: []) + show figure: it => { + set text(fontsize) + set align(center) + let has_caption = it.caption != none + if it.kind == image [ + #box[ + #it.body + #v(fontsize, weak: true) + Figure #it.caption + ] + ] else if it.kind == table [ + #box[ + #if has_caption{ + text("Table") + it.caption + } + #v(fontsize, weak: true) + #it.body + ] + + ] else [ + ... + ] + } + set table(stroke: 0.5pt) + show table: set text(fontsize) + + // Configure lists. + // set enum(indent: first-line-indent) + // set list(indent: first-line-indent) + + set heading(numbering: "1.") + show heading: it => { + if it.body in ([Appendices],[Acknowledgment], [Acknowledgement]){ + text(it.body, size: title-fontsize, weight: "bold") + }else if it.body in ([Contents], ){ + align(center)[ + #text(it.body, size: title-fontsize, weight: "bold") + ] + } + else{ + pad(left: -first-line-indent)[#it] + } + } + + show: cover.with(title: title) + + // contents + set page(margin: (left: 60pt, right: 40pt, top: 60pt, bottom: 40pt)) + set par( + first-line-indent: 0pt, + hanging-indent: 0pt, + ) + show outline.entry.where(level: 1): it => { + v(fontsize, weak: true) + + strong(it) + + } + pagebreak() + outline(indent: auto) + + // Settings for main body + set par( + // first-line-indent: first-line-indent, + //hanging-indent: -first-line-indent, + linebreaks: "optimized", + ) + + let page_counter = counter(page) + page_counter.update(0) + + set page( + margin: (left: 80pt, right: 50pt, top: 60pt, bottom: 40pt), + ) + + // Display the paper's main body. + body +}