[sw] SW build documentation

- added sw/doc/sw_build_flow.md that talks about the SW build flow using
the centrallized Makefile
diff --git a/doc/ug/getting_started_sw.md b/doc/ug/getting_started_sw.md
index e988525..d4b0c7c 100644
--- a/doc/ug/getting_started_sw.md
+++ b/doc/ug/getting_started_sw.md
@@ -7,8 +7,8 @@
 ## Building software
 
 ```console
-$ cd $REPO_TOP/sw/examples/hello_world
-$ make CC=/tools/riscv/bin/riscv32-unknown-elf-gcc
+$ cd $REPO_TOP/sw
+$ make SW_DIR=examples/hello_world CC=/tools/riscv/bin/riscv32-unknown-elf-gcc
 ```
 
 The build process produces a variety of output files.
@@ -17,3 +17,5 @@
 * `.bin`: the linked program as plain binary
 * `.dis`: the disassembled program
 * `.vmem`: a Verilog memory file which can be read by `$readmemh()` in Verilog code
+
+Please see [SW build flow](../../sw/doc/sw_build_flow.md) for more details.
diff --git a/doc/ug/getting_started_verilator.md b/doc/ug/getting_started_verilator.md
index 9f044dd..77a91f8 100644
--- a/doc/ug/getting_started_verilator.md
+++ b/doc/ug/getting_started_verilator.md
@@ -26,6 +26,7 @@
 For that purpose compile the demo program with "simulation" settings, which adjusts the frequencies to better match the simulation speed.
 In the instrcutions below, `SW_DIR` is a requirement argument, while `SW_BUILD_DIR` is not a required argument.
 If `SW_BUILD_DIR` argument is not supplied, the default location of the of output files are in `SW_DIR`
+Please see [SW build flow](../../sw/doc/sw_build_flow.md) for more details.
 
 ```console
 $ cd $REPO_TOP
diff --git a/sw/Makefile b/sw/Makefile
index 056dd30..57d0b31 100644
--- a/sw/Makefile
+++ b/sw/Makefile
@@ -4,6 +4,9 @@
 
 ####################################################################################################
 ## Generate a baremetal application for the microcontroller                                       ##
+##                                                                                                ##
+## Documentation: doc/sw_build_flow.md                                                            ##
+##                                                                                                ##
 ## Mandatory variables that need to be set over the command line:                                 ##
 ## SW_DIR:       this is the partial directory path to the SW test being built starting from sw/  ##
 ##               ex: if running hello_world.c, then SW_DIR=examples/hello_world                   ##
diff --git a/sw/doc/sw_build_flow.md b/sw/doc/sw_build_flow.md
new file mode 100644
index 0000000..c2f8566
--- /dev/null
+++ b/sw/doc/sw_build_flow.md
@@ -0,0 +1,121 @@
+{{% lowrisc-doc-hdr SW build flow }}
+
+{{% toc 3 }}
+
+## Overview
+The centralized Makefile flow attempts to maximize reuse of commonly used
+variables and rules among various software build targets (boot_rom, lib and
+main software tests.
+
+## Terminology / Some Make variables of interest
+- **SW_ROOT_DIR**: The root directory for all of opentitan SW is sw/ and is
+  indicated in the Make flow as `SW_ROOT_DIR`.
+
+- **sw**: A 'software' (abbreviated as SW) is considered to be the top level
+  SW application that is built through the final `vmem` image. For most tests, the
+  targets are boot_rom and SW test application. Variables prefixed with `SW_`
+  pertain to building the target SW application.
+
+- **SW_SRCS**: The sources needed for compiling SW are indicated using the
+  variable `SW_SRCS`.
+
+- **SW_DIR**: The directory containing the SW sources is indicated using the
+  variable `SW_DIR`. Note that `SW_DIR` is only the partial directory starting
+  from the `SW_ROOT_DIR`. It is **mandatory** to set this variable on the command
+  line.
+
+- **SW_NAME**: A `SW_DIR` could cotain one or more unique SW build targets.
+  This variable is used to indicate which one is to be built, on the command
+  line.
+
+- **lib**: This refers to the library code generated from the shared common
+  sources. These sources are currently placed in `sw/lib`, `sw/util` and
+  `sw/exts` directories. More such directories can be added in future.
+  Also, this is one of the goals of the make flow.
+
+- **LIB_SRCS**: This is a list of all common / shared sources compiled into the
+  lib archive. These include all of the required sources indicated in the
+  directories listed above.
+
+- **SW_BUILD_DIR**: This variable is the output directory to place all the
+  generated output files. This includes object files, intermediate dependency
+  files, generated linker scripts, elf, binary image, generated register header
+  files, disassembled code, vmem, among other things. By default, this is set to
+  the `SW_DIR`. It can be overridden on the command line. During compilation, the
+  `SW_BUILD_DIR/lib` directory is created and is used to put all the object files
+  and the archive file associated with `lib`.
+
+The variables listed here are not exhaustive, but bare minimum to indicate to
+the users the most typical use cases. Users are encouraged to read through
+the files listed below for more details.
+
+## Organization
+The SW build Makefiles are organized as follows:
+
+- **`sw/Makefile`**: The top level SW build Makefile (`sw/Makefile`). All of the
+  sub-make files are included directly or indirectly into this. This is the
+  starting point for compiling any target.
+
+- **`sw/opts.mk`**: All commonly used Make variables in one place. This sub-make
+  file is also used to check if certain switches are enabled and further modify /
+  customize the flow for target being built. An example of this is using the `TARGET`
+  variable to change how SW is built for DV vs FPGA / Verilator / production SW.
+
+- **`sw/rules.mk`**: All rules for generating all the outputs in one place.
+
+These three form the *base-make files* for the SW build. Any directory containing
+sources for building the SW needs to have an associated `srcs.mk` sub-make file
+within that directory. These `srcs.mk` files are then required to be added to the
+top level SW build Makefile.
+
+- **`exts/common/srcs.mk`**: Additional extended common sources. This includes
+    the default `CRT_SRCS` and the `LINKER_SCRIPT` which can be overridden for
+    sw specific requirements.
+
+- **`lib/srcs.mk`**: Directory containing sources to compile the lib elements and
+  its dependencies.
+
+- **`$(SW_DIR)/srcs.mk`**: This sub-make file contains sources for building a SW
+  target is indicated using `SW_NAME`. This file is included in the top level
+  SW build Makefile. Setting the **`SW_DIR` and `SW_NAME` correctly is
+  required for building the desired image**. The existing variables in
+  `opts.mk` can be overridden or appended to in this sub-make file to further
+  customize the build target based on need. If this directory contains only a
+  single SW build target, then `SW_NAME` can be set to the same name (typically
+  same name as the directory and the C source) in this file. In that case, indicating
+  `SW_NAME` on the command line is not required.
+
+- **`exts/common/srcs.mk`**: Additional extended common sources. This includes
+    the default `CRT_SRCS` and the `LINKER_SCRIPT` which can be overridden for
+    sw specific requirements.
+
+## How to build SW
+The examples indicated below assume that the present working directory is
+`SW_ROOT_DIR`. As indicated in the previous sections, `SW_DIR` and `SW_NAME` are
+mandatory variables that need to be set correctly on the command line. `SW_NAME`
+is optional if `SW_DIR` has only one SW target and `SW_NAME` is set in
+`$(SW_DIR)/srcs.mk` file. `SW_BUILD_DIR` is optional.
+
+Build boot_rom:
+```console
+$ make SW_DIR=boot_rom SW_NAME=boot_rom
+```
+
+This will build the boot_rom image in the boot_rom directly itself. SW_NAME in
+boot_rom/srcs.mk is already set to boot_rom, so there is no need to specify it
+on the command line.
+
+- Build the boot_rom in a separate build directory:
+```console
+$ make SW_DIR=boot_rom SW_BUILD_DIR=path/to/scratch
+```
+
+- Build hello_world test:
+```console
+$ make SW_DIR=examples/hello_world SW_NAME=hello_world SW_BUILD_DIR=path/to/scratch
+```
+
+- Build sha256 test:
+```console
+$ make SW_DIR=tests/hmac SW_NAME=sha256_test
+```
diff --git a/sw/opts.mk b/sw/opts.mk
index bcb633b..c89f3bb 100644
--- a/sw/opts.mk
+++ b/sw/opts.mk
@@ -4,6 +4,9 @@
 #
 ####################################################################################################
 ## SW build infrastructure - common opts                                                          ##
+##                                                                                                ##
+## Documentation: doc/sw_build_flow.md                                                            ##
+##                                                                                                ##
 ## Two types of embedded SW is built typically for a test - boot_rom and sw test application.     ##
 ## Each has two components - top level sources (indicated with SW_ prefix) and libraries          ##
 ## (indicated with LIB_ prefix.                                                                   ##
diff --git a/sw/rules.mk b/sw/rules.mk
index f1af2d7..aa42f9f 100644
--- a/sw/rules.mk
+++ b/sw/rules.mk
@@ -4,6 +4,9 @@
 
 ##############################################################
 ## Generic rules set for compiling SW for different targets ##
+##                                                          ##
+## Documentation: doc/sw_build_flow.md                      ##
+##                                                          ##
 ##############################################################
 
 # rules