[dv,sw] sw Makefile refactor

[sw] Makefile refactor

- added centrallized Makefile infra for maximizing reuse across SW
test, lib and boot_rom targets
- existing Make flows still remain (for the timebeing; will remove it
once all approve of this)
- all make commands are to be run from sw/ area
- updated with chip_info generation
- TODOs
  - add some documentation
  - need to fix support for external apps, eg coremark

[dv,sw] coremark port now works

- updates to get external app (coremark) compiling with the refactored
flow
- added ability to compile targets with external Makefiles with
STANDALONE_SW var
- added sw/benchmarks/srcs.mk to supply STANDALONE_CMD to build custom
app

[dv,sw] removed existing Makefiles (deprecated)
diff --git a/hw/dv/tools/Makefile b/hw/dv/tools/Makefile
index 7f7fab6..1f7ab76 100644
--- a/hw/dv/tools/Makefile
+++ b/hw/dv/tools/Makefile
@@ -29,8 +29,8 @@
 BUILD_DIR         := ${SCRATCH_PATH}/${BUILD_LOC}
 RUN_PATH          ?= ${SCRATCH_PATH}/${TEST_NAME}
 RUN_DIR           := ${RUN_PATH}/${RUN_LOC}
-
-SW_DIR            := ${PRJ_DIR}/sw
+SW_BUILD_DIR      ?= ${RUN_DIR}/sw_build
+SW_ROOT_DIR       := ${PRJ_DIR}/sw
 
 JOB_OPTS          ?=
 BUILD_JOB_OPTS    ?= $(JOB_OPTS)
@@ -44,13 +44,27 @@
 BUILD_LOG         ?= ${BUILD_DIR}/build.log
 RUN_LOG           ?= ${RUN_DIR}/run.log
 UVM_VERBOSITY     ?= UVM_LOW
-BUILD_OPTS        +=
-# command line version of BUILD_OPTS - CL_BUILD_OPTS - it should be empty here
+
+####################################################################################################
+## Options for SV build / C build / simulation run                                                ##
+## CL_ prefix represents command line versions of these options - they should be empty and only   ##
+## be set on the command line                                                                     ##
+####################################################################################################
+# BUILD_OPTS are passed to the simulator during the SV testbench compile step
 CL_BUILD_OPTS     +=
-RUN_OPTS          += +UVM_NO_RELNOTES
-# command line version of RUN_OPTS - CL_RUN_OPTS - it should be empty here
+BUILD_OPTS        +=
+
+# RUN_OPTS are passed to the simulation executable that is invoked to run the simulation
 CL_RUN_OPTS       +=
-CAPP_BUILD_OPTS   ?=
+RUN_OPTS          += +UVM_NO_RELNOTES
+
+# SW_OPTS are options for SW apps that come with their own Makefile (example coremark)
+CL_SW_OPTS        +=
+SW_OPTS           += ${CL_SW_OPTS}
+
+# SW_FLAGS are compiler flags / directives that we can pass for each test using our own Makefiles
+CL_SW_FLAGS       +=
+SW_FLAGS          += ${CL_SW_FLAGS}
 
 # default project-wide bus widths
 TL_AW             ?= 32
diff --git a/hw/dv/tools/rules.mk b/hw/dv/tools/rules.mk
index bb2eaea..864727c 100644
--- a/hw/dv/tools/rules.mk
+++ b/hw/dv/tools/rules.mk
@@ -42,24 +42,21 @@
 	/bin/bash ${MAKE_ROOT}/run_dir_limiter ${RUN_PATH} ${RUN_DIR_LIMIT}
 	env > ${RUN_DIR}/env_vars
 
-# TODO: clean this (capp tooling infrastructure)
-capp: pre_run
-ifneq (${CAPP_NAME},)
-	# Recursive make calls
-	make distclean -C ${SW_DIR}/boot_rom
-	make -C ${SW_DIR}/boot_rom
-	make distclean -C ${SW_DIR}/${CAPP_DIR} MAKEFLAGS=$(CAPP_BUILD_OPTS)
-	make -C ${SW_DIR}/${CAPP_DIR} MAKEFLAGS=$(CAPP_BUILD_OPTS) \
-	PROGRAM_CFLAGS=$(PROGRAM_CFLAGS)
-
-	# Copy outputs over to run area
-	cp $(SW_DIR)/boot_rom/boot_rom.vmem ${RUN_DIR}/rom.vmem
-	cp ${SW_DIR}/${CAPP_DIR}/${CAPP_NAME}.vmem ${RUN_DIR}/main.vmem
-	cp ${SW_DIR}/${CAPP_DIR}/${CAPP_NAME}.dis ${RUN_DIR}/main.dis
-	cp ${SW_DIR}/${CAPP_DIR}/${CAPP_NAME}.map ${RUN_DIR}/main.map
+sw_build: pre_run
+ifneq (${SW_NAME},)
+	mkdir -p ${SW_BUILD_DIR}
+	$(MAKE) -C $(SW_ROOT_DIR) \
+	  SW_DIR=boot_rom \
+	  SW_BUILD_DIR=$(SW_BUILD_DIR)/rom \
+	  MAKEFLAGS="$(SW_OPTS)"
+	$(MAKE) -C $(SW_ROOT_DIR) \
+	  SW_DIR=$(SW_DIR) \
+	  SW_NAME=$(SW_NAME) \
+	  SW_BUILD_DIR=$(SW_BUILD_DIR)/sw \
+	  MAKEFLAGS="$(SW_OPTS)"
 endif
 
-simulate: capp
+simulate: sw_build
 	$(RUN_JOB_OPTS) cd ${RUN_DIR} && ${SIMX} ${RUN_OPTS} ${CL_RUN_OPTS}
 
 post_run: simulate
@@ -77,6 +74,7 @@
 	compile \
 	post_compile \
 	compile_result \
+	sw_build \
 	pre_run \
 	simulate \
 	post_run \
diff --git a/hw/top_earlgrey/dv/Makefile b/hw/top_earlgrey/dv/Makefile
index f7d1896..000b2e1 100644
--- a/hw/top_earlgrey/dv/Makefile
+++ b/hw/top_earlgrey/dv/Makefile
@@ -16,7 +16,6 @@
 DV_DIR          := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
 export DUT_TOP  := top_earlgrey_asic
 export TB_TOP   := tb
-export RV_TOOLS := /edascratch/ms_edatools/riscv-tools/rv32ic/bin
 FUSESOC_CORE    := lowrisc:dv:chip_sim:0.1
 COMPILE_KEY     ?= default
 
@@ -28,33 +27,33 @@
 UVM_TEST_SEQ    ?= chip_base_vseq
 
 ifeq (${TEST_NAME},chip_sanity)
-  CAPP_DIR       = examples/hello_world
-  CAPP_NAME      = hello_world
+  SW_DIR         = examples/hello_world
+  SW_NAME        = hello_world
 endif
 
 ifeq (${TEST_NAME},chip_flash_test)
-  CAPP_DIR       = tests/flash_ctrl
-  CAPP_NAME      = flash_test
+  SW_DIR         = tests/flash_ctrl
+  SW_NAME        = flash_test
   RUN_OPTS      += +cpu_test_timeout_ns=15000000
 endif
 
 ifeq (${TEST_NAME},chip_sha256_test)
-  CAPP_DIR       = tests/hmac
-  CAPP_NAME      = sha256_test
+  SW_DIR         = tests/hmac
+  SW_NAME        = sha256_test
   RUN_OPTS      += +cpu_test_timeout_ns=4000000
 endif
 
 ifeq (${TEST_NAME},chip_rv_timer_test)
-  CAPP_DIR       = tests/rv_timer
-  CAPP_NAME      = rv_timer_test
+  SW_DIR         = tests/rv_timer
+  SW_NAME        = rv_timer_test
   RUN_OPTS      += +cpu_test_timeout_ns=4000000
 endif
 
 ifeq (${TEST_NAME},coremark)
-  CAPP_DIR         = coremark
-  CAPP_NAME        = coremark
+  SW_DIR           = benchmarks/coremark
+  SW_NAME          = coremark
   RUN_OPTS        += +cpu_test_timeout_ns=20000000
-  CAPP_BUILD_OPTS += ITERATIONS=1
+  SW_OPTS         += ITERATIONS=1
 endif
 
 ifeq (${TEST_NAME},chip_csr_hw_reset)
diff --git a/hw/top_earlgrey/dv/env/chip_env_pkg.sv b/hw/top_earlgrey/dv/env/chip_env_pkg.sv
index c3a1e8a..17b532c 100644
--- a/hw/top_earlgrey/dv/env/chip_env_pkg.sv
+++ b/hw/top_earlgrey/dv/env/chip_env_pkg.sv
@@ -26,7 +26,10 @@
   `include "dv_macros.svh"
 
   // local parameters and types
-  parameter NUM_GPIOS = 16;
+  parameter         NUM_GPIOS   = 16;
+  parameter string  ROM_MEM_IMG = "sw_build/rom/rom.vmem";
+  parameter string  SW_MEM_IMG  = "sw_build/sw/sw.vmem";
+
   typedef virtual pins_if #(NUM_GPIOS)  gpio_vif;
   typedef virtual mem_bkdr_if           mem_bkdr_vif;
 
diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv
index 833ba89..ab06770 100644
--- a/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv
+++ b/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv
@@ -46,12 +46,12 @@
   // routine to backdoor load cpu test hex image and bring the cpu out of reset (if required)
   // TODO(sriyerg): for future implementation
   virtual task cpu_init();
-    cfg.mem_bkdr_vifs[Rom].load_mem_from_file("rom.vmem");
+    cfg.mem_bkdr_vifs[Rom].load_mem_from_file(ROM_MEM_IMG);
     cfg.mem_bkdr_vifs[FlashBank0].set_mem();
     cfg.mem_bkdr_vifs[FlashBank1].set_mem();
 
     // TODO: the location of the main execution image should be randomized for either bank in future
-    cfg.mem_bkdr_vifs[FlashBank0].load_mem_from_file("main.vmem");
+    cfg.mem_bkdr_vifs[FlashBank0].load_mem_from_file(SW_MEM_IMG);
     cpu_test_state = CpuTestRunning;
   endtask
 
diff --git a/sw/Makefile b/sw/Makefile
new file mode 100644
index 0000000..056dd30
--- /dev/null
+++ b/sw/Makefile
@@ -0,0 +1,34 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+####################################################################################################
+## Generate a baremetal application for the microcontroller                                       ##
+## 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                   ##
+##               At this location, there needs to be a 'srcs.mk' file that contains the list of   ##
+##               SW_SRCS to be built for that SW test.                                            ##
+## SW_NAME:      This is the name of the SW test begin run. Optional if SW_DIR name (last dir) is ##
+##               the same as the SW test name.                                                    ##
+##                                                                                                ##
+## Optional variables:                                                                            ##
+## SW_BUILD_DIR: This is the output location for generating all sources                           ##
+## SW_FLAGS      Global args to pass on to the compiler                                           ##
+## SW_OPTS       Global args to pass on to the sub-make commands                                  ##
+####################################################################################################
+
+
+# Generate a baremetal application for the microcontroller
+SW_ROOT_DIR   := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
+SW_DIR        ?= examples/hello_world
+
+# sources
+STANDALONE_SW ?= 0
+include ${SW_DIR}/srcs.mk
+include exts/common/srcs.mk
+include lib/srcs.mk
+
+# common options and rules
+include opts.mk
+include rules.mk
diff --git a/sw/benchmarks/coremark/Makefile b/sw/benchmarks/coremark/Makefile
deleted file mode 100644
index 0fa4dfb..0000000
--- a/sw/benchmarks/coremark/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-#
-# Generate a baremetal application for the microcontroller
-
-NAME          := coremark
-PROGRAM_DIR   := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
-COREMARK_DIR  := $(PROGRAM_DIR)/../../vendor/$(NAME)
-COREMARK_PORT := $(PROGRAM_DIR)/top_earlgrey
-
-all:
-#	$(MAKE) -C $(LIB_DIR) MAKEFLAGS=$(MAKEFLAGS)
-	$(MAKE) -C $(LIB_DIR)
-	$(MAKE) -C $(COREMARK_DIR) PORT_DIR=$(COREMARK_PORT)
-	$(foreach out, $(OUTFILES), cp $(COREMARK_DIR)/$(out) .;)
-
-
-distclean:
-	$(RM) $(OUTFILES)
-	$(MAKE) -C $(LIB_DIR) distclean
-	$(MAKE) -C $(COREMARK_DIR) clean PORT_DIR=$(COREMARK_PORT)
-
-include ${PROGRAM_DIR}/../../exts/common/options.mk
diff --git a/sw/benchmarks/coremark/srcs.mk b/sw/benchmarks/coremark/srcs.mk
new file mode 100644
index 0000000..369286c
--- /dev/null
+++ b/sw/benchmarks/coremark/srcs.mk
@@ -0,0 +1,13 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+COREMARK_DIR     = $(SW_ROOT_DIR)/vendor/$(SW_NAME)
+COREMARK_PORT    = $(SW_ROOT_DIR)/$(SW_DIR)/top_earlgrey
+STANDALONE_SW   := 1
+STANDALONE_CMD   = $(MAKE) $(IMG_OUTPUTS) -C $(COREMARK_DIR) \
+                     PORT_DIR=$(COREMARK_PORT) \
+                     SW_DIR=$(SW_DIR) \
+                     SW_ROOT_DIR=$(SW_ROOT_DIR) \
+                     SW_BUILD_DIR=$(SW_BUILD_DIR) \
+                     MAKEFLAGS=$(MAKEFLAGS)
diff --git a/sw/benchmarks/coremark/top_earlgrey/core_portme.mak b/sw/benchmarks/coremark/top_earlgrey/core_portme.mak
index 739e251..cd45021 100755
--- a/sw/benchmarks/coremark/top_earlgrey/core_portme.mak
+++ b/sw/benchmarks/coremark/top_earlgrey/core_portme.mak
@@ -1,82 +1,90 @@
 #File : core_portme.mak
 
-NAME         = coremark
-PORTME_DIR  := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
-PROGRAM_DIR := $(PORTME_DIR)/../
+include ${SW_ROOT_DIR}/opts.mk
 
-include ${PROGRAM_DIR}/../../exts/common/options.mk
-PORT_CLEAN  := $(OUTFILES)
+PORT_CLEAN  := $(IMG_OUTPUTS)
 
+# FLAG : EXE, OEXT
+# Extensions of generated outputs
+OEXT = .o
+EXE  = .elf
+
+# FLAG : OPATH
+# Path to the output folder. Default - current folder.
+OPATH = $(SW_BUILD_DIR)/
 
 # Flag : OUTFLAG
-#	Use this flag to define how to to get an executable (e.g -o)
-OUTFLAG= -T $(LINKER_SCRIPT) -L$(LIB_DIR) -l$(LIB_NAME) -Xlinker -Map=coremark.map -o
-# Flag : CC
-#	Use this flag to define compiler to use
-CC 		= $(RV_TOOLS)/riscv32-unknown-elf-gcc
-# Flag : LD
-#	Use this flag to define compiler to use
-LD		= $(RV_TOOLS)/riscv32-unknown-elf-ld
-# Flag : AS
-#	Use this flag to define compiler to use
-AS		= $(RV_TOOLS)/riscv32-unknown-elf-as
-# Flag : CFLAGS
-#	Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags"
-PORT_CFLAGS = -DTOTAL_DATA_SIZE=6000 -DMAIN_HAS_NOARGC=1
-FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
-CFLAGS += $(PORT_CFLAGS) $(XCFLAGS) -I$(PORT_DIR) -I. -I$(LIB_DIR)
-#Flag : LFLAGS_END
-#	Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts).
-#	Note : On certain platforms, the default clock_gettime implementation is supported but requires linking of librt.
-#SEPARATE_COMPILE=1
-# Flag : SEPARATE_COMPILE
-# You must also define below how to create an object file, and how to link.
-OBJOUT 	= -o
-LFLAGS 	=
-ASFLAGS =
-OFLAG 	= -o
-COUT 	= -c
+# Use this flag to define how to to get an executable (e.g -o)
+OUTFLAG = $(LINK_OPTS) -o
 
+# Flag : CFLAGS
+# Use this flag to define compiler options. Note, you can add compiler options
+# from the command line using XCFLAGS="other flags"
+PORT_CFLAGS  = -DTOTAL_DATA_SIZE=6000 -DMAIN_HAS_NOARGC=1
+FLAGS_STR    = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
+CFLAGS      += $(PORT_CFLAGS) $(XCFLAGS) -I$(PORT_DIR) -I. $(INCS)
+
+# Flag : LFLAGS_END
+# Define any libraries needed for linking or other flags that should come
+# at the end of the link line (e.g. linker scripts).
+# Note : On certain platforms, the default clock_gettime implementation
+# is supported but requires linking of librt.
 LFLAGS_END =
+
+# Flag : SEPARATE_COMPILE
+# Do compile and link steps separately. Not needed at this point.
+
+# You must also define below how to create an object file, and how to link.
+OBJOUT  = -o
+LFLAGS  =
+ASFLAGS =
+OFLAG   = -o
+COUT    = -c
+
 # Flag : PORT_SRCS
-# 	Port specific source files can be added here
-#	You may also need cvt.c if the fcvt functions are not provided as intrinsics by your compiler!
+# Port specific source files can be added here
+# You may also need cvt.c if the fcvt functions are not provided as intrinsics by your compiler!
 PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/ee_printf.c $(EXT_SRCS)
 vpath %.c $(PORT_DIR)
 vpath %.s $(PORT_DIR)
 
 # Flag : LOAD
-#	For a simple port, we assume self hosted compile and run, no load needed.
+# For a simple port, we assume self hosted compile and run, no load needed.
 
 # Flag : RUN
-#	For a simple port, we assume self hosted compile and run, simple invocation of the executable
+# For a simple port, we assume self hosted compile and run, simple invocation of the executable
+
+# Flag : MKDIR
+MKDIR = mkdir -p
 
 LOAD = echo "Please set LOAD to the process of loading the executable to the flash"
 RUN = echo "Please set LOAD to the process of running the executable (e.g. via jtag, or board reset)"
 
-OEXT = .o
-EXE = .elf
-
-$(OPATH)$(PORT_DIR)/%$(OEXT) : %.c
-	$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
-
 $(OPATH)%$(OEXT) : %.c
 	$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
 
-$(OPATH)$(PORT_DIR)/%$(OEXT) : %.s
+$(OPATH)%$(OEXT) : %.s
 	$(AS) $(ASFLAGS) $< $(OBJOUT) $@
 
+$(OPATH)%$(OEXT) : $(PORT_DIR)/%.c
+	$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
+
+$(OPATH)%$(OEXT) : $(PORT_DIR)/%.s
+	$(AS) $(ASFLAGS) $< $(OBJOUT) $@
+
+%.vmem: %.bin
+	srec_cat $^ -binary -offset 0x0 -byte-swap 4 -o $@ -vmem
+
+%.bin: %.elf
+	$(OBJCOPY) -O binary $^ $@
+
+%.dis: %.elf
+	$(OBJDUMP) -SD $^ > $@
+
+$(SW_BUILD_DIR)/$(IMG_NAME).elf: $(OUTFILE)
+	$(MAKE) $(OUTFILE)
+	mv $(OUTFILE) $@
+
 # Target : port_pre% and port_post%
-# For the purpose of this simple port, no pre or post steps needed.
 
 .PHONY : port_clean port_prebuild port_postbuild port_prerun port_postrun port_preload port_postload
-
-port_postbuild:
-	$(RV_TOOLS)/riscv32-unknown-elf-objcopy -O binary coremark.elf coremark.bin
-	srec_cat coremark.bin -binary -offset 0x0 -byte-swap 4 -o coremark.vmem -vmem
-	$(RV_TOOLS)/riscv32-unknown-elf-objdump -SD coremark.elf > coremark.dis
-
-# FLAG : OPATH
-# Path to the output folder. Default - current folder.
-OPATH = ./
-MKDIR = mkdir -p
diff --git a/sw/boot_rom/Makefile b/sw/boot_rom/Makefile
deleted file mode 100644
index c5dd590..0000000
--- a/sw/boot_rom/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-#
-# Generate a baremetal application for the microcontroller
-
-NAME          = boot_rom
-SRCS          = bootstrap.c boot_rom.c
-LINKER_SCRIPT = rom_link.ld
-CRT_SRCS      =
-EXT_ASMS      = crt0.S
-CHIP_INFO     = chip_info.h
-
-PROGRAM_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
-SW_DIR      := $(PROGRAM_DIR)/..
-
-include ${PROGRAM_DIR}/../exts/common/options.mk
-include ${PROGRAM_DIR}/../exts/common/common.mk
diff --git a/sw/boot_rom/srcs.mk b/sw/boot_rom/srcs.mk
new file mode 100644
index 0000000..456df0c
--- /dev/null
+++ b/sw/boot_rom/srcs.mk
@@ -0,0 +1,10 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+SW_NAME       ?= boot_rom
+SW_SRCS       += $(SW_DIR)/bootstrap.c $(SW_DIR)/boot_rom.c
+
+# overrides
+CRT_SRCS      := $(SW_DIR)/crt0.S
+LINKER_SCRIPT := $(SW_DIR)/rom_link.ld
diff --git a/sw/examples/hello_usbdev/Makefile b/sw/examples/hello_usbdev/Makefile
deleted file mode 100644
index 2814e8d..0000000
--- a/sw/examples/hello_usbdev/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-#
-# Generate a baremetal application for the project
-
-NAME         = hello_usbdev
-SRCS         = $(NAME).c
-PROGRAM_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
-
-include ${PROGRAM_DIR}/../../exts/common/options.mk
-include ${PROGRAM_DIR}/../../exts/common/common.mk
diff --git a/sw/examples/hello_usbdev/srcs.mk b/sw/examples/hello_usbdev/srcs.mk
new file mode 100644
index 0000000..26811ac
--- /dev/null
+++ b/sw/examples/hello_usbdev/srcs.mk
@@ -0,0 +1,5 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+SW_SRCS += $(SW_DIR)/hello_usbdev.c
diff --git a/sw/examples/hello_world/Makefile b/sw/examples/hello_world/Makefile
deleted file mode 100644
index f947497..0000000
--- a/sw/examples/hello_world/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-#
-# Generate a baremetal application for the microcontroller
-
-NAME         = hello_world
-SRCS         = hello_world.c
-PROGRAM_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
-
-include ${PROGRAM_DIR}/../../exts/common/options.mk
-include ${PROGRAM_DIR}/../../exts/common/common.mk
diff --git a/sw/examples/hello_world/srcs.mk b/sw/examples/hello_world/srcs.mk
new file mode 100644
index 0000000..4cf4756
--- /dev/null
+++ b/sw/examples/hello_world/srcs.mk
@@ -0,0 +1,5 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+SW_SRCS += $(SW_DIR)/hello_world.c
diff --git a/sw/exts/common/srcs.mk b/sw/exts/common/srcs.mk
new file mode 100644
index 0000000..e50b681
--- /dev/null
+++ b/sw/exts/common/srcs.mk
@@ -0,0 +1,10 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+EXT_COMMON_DIR        ?= $(SW_ROOT_DIR)/exts/common
+INCS                  += -I$(EXT_COMMON_DIR)
+
+EXT_COMMON_LOC_SRCS   +=
+
+EXT_SRCS              += $(addprefix $(EXT_COMMON_DIR)/, $(EXT_COMMON_LOC_SRCS))
diff --git a/sw/lib/Makefile b/sw/lib/Makefile
deleted file mode 100644
index 5220ca0..0000000
--- a/sw/lib/Makefile
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-#
-# Generate a baremetal application for the microcontroller
-
-DIF_SRCS     = uart.c gpio.c spi_device.c flash_ctrl.c hmac.c usbdev.c rv_timer.c
-EXT_SRCS     = usb_controlep.c usb_simpleserial.c irq.c handler.c hw_sha256.c
-EXT_ASMS     = irq_vectors.S
-GENHDRS     := ${DIF_SRCS:.c=_regs.h}
-GENHDR_BASE := ${DIF_SRCS:.c=}
-ARCH         = rv32imc
-# ARCH = rv32im # to disable compressed instructions
-
-RV_TOOLS    ?= /tools/riscv/bin
-
-INCS        += -I../vendor
-CC          := ${RV_TOOLS}/riscv32-unknown-elf-gcc
-CFLAGS      ?= -Wall -g -Os -march=$(ARCH) -mabi=ilp32 -static -mcmodel=medany \
-               -fvisibility=hidden -nostdlib -nostartfiles $(INCS)
-
-
-ifeq ($(SIM),1)
-  CFLAGS    += -DSIMULATION
-endif
-
-AR          := $(subst gcc,ar,$(wordlist 1,1,$(CC)))
-ARFLAGS     := rc
-
-REGTOOL      = ../../util/regtool.py
-
-OBJS        := ${DIF_SRCS:.c=.o} ${EXT_SRCS:.c=.o} ${EXT_ASMS:.S=.o}
-DEPS         = $(OBJS:%.o=%.d)
-
-OUTFILES     = libot.a
-
-$(OUTFILES): $(OBJS)
-	$(AR) $(ARFLAGS) $@ $(OBJS)
-
-all: $(OUTFILES)
-
-define header_gen
-    $1.c: $1_regs.h
-
-    $1_regs.h: ../../hw/ip/$1/doc/*.hjson
-	if [ -f ../../hw/ip/$1/doc/$1.hjson ]; then \
-		$(REGTOOL) -D -o $1_regs.h ../../hw/ip/$1/doc/$1.hjson ; \
-	else \
-		$(REGTOOL) -D -o $1_regs.h ../../hw/ip/$1/doc/$1_reg.hjson ; \
-	fi
-endef
-$(foreach f,$(GENHDR_BASE),$(eval $(call header_gen,$f)))
-
--include $(DEPS)
-
-clean:
-	$(RM) *.o *.d $(GENHDRS)
-
-distclean: clean
-	$(RM) $(OUTFILES)
diff --git a/sw/lib/srcs.mk b/sw/lib/srcs.mk
new file mode 100644
index 0000000..609e7a8
--- /dev/null
+++ b/sw/lib/srcs.mk
@@ -0,0 +1,9 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+GEN_HEADERS       += $(LIB_LOC_DIF_SRCS:.c=_regs.h) chip_info.h
+LIB_LOC_DIF_SRCS  += uart.c gpio.c spi_device.c flash_ctrl.c hmac.c usbdev.c rv_timer.c
+LIB_LOC_EXT_SRCS  += usb_controlep.c usb_simpleserial.c irq.c handler.c irq_vectors.S
+
+LIB_SRCS          += $(addprefix $(LIB_DIR)/, $(LIB_LOC_DIF_SRCS) $(LIB_LOC_EXT_SRCS))
diff --git a/sw/opts.mk b/sw/opts.mk
new file mode 100644
index 0000000..c3eaf0c
--- /dev/null
+++ b/sw/opts.mk
@@ -0,0 +1,78 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+#
+####################################################################################################
+## SW build infrastructure - common opts                                                          ##
+## 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.                                                                   ##
+## If a new dir with SW or LIB sources are added, a 'srcs.mk' needs to be included and it should  ##
+## specify the additional sources either via SW_SRCS or LIB_SRCS variable, See existing examples  ##
+## for reference.                                                                                 ##
+####################################################################################################
+
+# sources and targets
+SW_NAME       ?= $(notdir $(SW_DIR))
+SW_SRCS       := $(CRT_SRCS) $(SW_SRCS)
+SW_OBJS       += $(addprefix $(SW_BUILD_DIR)/, $(addsuffix .o, $(basename $(notdir $(SW_SRCS)))))
+SW_PPOS       += $(SW_OBJS:.o=.ppo)
+SW_DEPS       ?= lib
+SW_BUILD_DIR  ?= $(SW_ROOT_DIR)/$(SW_DIR)
+
+LIB_NAME      ?= ot
+LIB_DIR       ?= $(SW_ROOT_DIR)/lib
+LIB_TARGET    ?= $(LIB_BUILD_DIR)/lib${LIB_NAME}.a
+LIB_SRCS      +=
+LIB_OBJS      += $(addprefix $(LIB_BUILD_DIR)/, $(addsuffix .o, $(basename $(notdir $(LIB_SRCS)))))
+LIB_PPOS      += $(LIB_OBJS:.o=.ppo)
+LIB_BUILD_DIR ?= $(SW_BUILD_DIR)/lib
+
+DEPS          += $(SW_OBJS:%.o=%.d) $(LIB_OBJS:%.o=%.d)
+INCS          += -I$(SW_DIR) -I$(LIB_DIR) -I$(SW_BUILD_DIR) -I$(LIB_BUILD_DIR)
+
+LINK_OPTS     += -T $(LINKER_SCRIPT)
+LINK_OPTS     += $(SW_OBJS) -L$(LIB_BUILD_DIR) -l$(LIB_NAME)
+LINK_OPTS     += -Xlinker -Map=${SW_BUILD_DIR}/${IMG_NAME}.map
+
+# target (either 'boot_rom' or 'sw')
+ifeq ($(SW_NAME),boot_rom)
+  IMG_NAME    ?= rom
+else
+  IMG_NAME    ?= sw
+endif
+
+IMG_OUTPUTS       += $(SW_BUILD_DIR)/$(IMG_NAME).elf \
+                     $(SW_BUILD_DIR)/$(IMG_NAME).map \
+                     $(SW_BUILD_DIR)/$(IMG_NAME).dis \
+                     $(SW_BUILD_DIR)/$(IMG_NAME).bin \
+                     $(SW_BUILD_DIR)/$(IMG_NAME).vmem
+GEN_HEADER_OUTPUTS = $(addprefix $(LIB_BUILD_DIR)/, $(GEN_HEADERS))
+
+# defaults
+CRT_SRCS      ?= $(EXT_COMMON_DIR)/_crt.c
+LINKER_SCRIPT ?= $(SW_ROOT_DIR)/exts/common/link.ld
+
+# tools and opts
+REGTOOL       ?= $(SW_ROOT_DIR)/../util/regtool.py
+INFOTOOL      ?= $(SW_ROOT_DIR)/../util/rom_chip_info.py
+
+RV_TOOLS      ?= /tools/riscv/bin
+# ARCH = rv32im # to disable compressed instructions
+ARCH           = rv32imc
+CC             = ${RV_TOOLS}/riscv32-unknown-elf-gcc
+AR             = $(subst gcc,ar,$(wordlist 1,1,$(CC)))
+AS             = $(subst gcc,as,$(wordlist 1,1,$(CC)))
+LD             = $(subst gcc,ld,$(wordlist 1,1,$(CC)))
+OBJCOPY        = $(subst gcc,objcopy,$(wordlist 1,1,$(CC)))
+OBJDUMP        = $(subst gcc,objdump,$(wordlist 1,1,$(CC)))
+
+CFLAGS        += -march=$(ARCH) -mabi=ilp32 -static -mcmodel=medany -Wall -g -Os \
+                 -fvisibility=hidden -nostdlib -nostartfiles $(SW_FLAGS)
+ARFLAGS        = rc
+
+# conditional flags
+SIM ?= 0
+ifeq ($(SIM),1)
+  CFLAGS      += -DSIMULATION
+endif
diff --git a/sw/rules.mk b/sw/rules.mk
new file mode 100644
index 0000000..f1af2d7
--- /dev/null
+++ b/sw/rules.mk
@@ -0,0 +1,133 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+##############################################################
+## Generic rules set for compiling SW for different targets ##
+##############################################################
+
+# rules
+.SECONDEXPANSION:
+ifeq ($(STANDALONE_SW), 1)
+all: gen_dir standalone
+else
+all: gen_dir $(IMG_OUTPUTS)
+endif
+
+gen_dir:
+	mkdir -p ${SW_BUILD_DIR}
+	mkdir -p ${LIB_BUILD_DIR}
+	env > ${SW_BUILD_DIR}/env_vars
+
+standalone: $(SW_DEPS)
+	$(STANDALONE_CMD)
+
+$(LIB_TARGET): $(GEN_HEADER_OUTPUTS) $(LIB_PPOS) $(LIB_OBJS)
+	$(AR) $(ARFLAGS) $@ $(LIB_OBJS)
+
+lib: $(LIB_TARGET)
+
+# Note: this IMG_NAME requires the srecord package to be installed.
+# XXX: This could be replaced by objcopy onc is merged.
+# https://sourceware.org/bugzilla/show_bug.cgi?id=19921
+# XXX: Currently the start address 0x1000 is hardcoded. It could/should be
+# read from the elf file, but is lost in the bin file.
+# Switching to objcopy will resolve that as well.
+%.vmem: %.bin
+	srec_cat $^ -binary -offset 0x0 -byte-swap 4 -o $@ -vmem
+
+%.bin: %.elf
+	$(OBJCOPY) -O binary $^ $@
+
+%.dis: %.elf
+	$(OBJDUMP) -SD $^ > $@
+
+# link & generate elf
+%.elf %.map: $(SW_DEPS) $(SW_PPOS) $(SW_OBJS) $(LINKER_SCRIPT)
+	$(CC) $(CFLAGS) $(LINK_OPTS) -o $@
+
+# compile sw sources
+# TOOD: figure out a way to 'templatise' .o/.ppo ruleset for each dir containing srcs
+
+$(SW_BUILD_DIR)/%.o: $(SW_DIR)/$$*.c
+	$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
+
+$(SW_BUILD_DIR)/%.o: $(SW_DIR)/$$*.S
+	$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
+
+$(SW_BUILD_DIR)/%.ppo: $(SW_DIR)/$$*.c
+	$(CC) $(CFLAGS) -E -MMD -c $(INCS) -o $@ $<
+
+$(SW_BUILD_DIR)/%.ppo: $(SW_DIR)/$$*.S
+	$(CC) $(CFLAGS) -E -MMD -c $(INCS) -o $@ $<
+
+$(SW_BUILD_DIR)/%.o: $(LIB_DIR)/$$*.c
+	$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
+
+$(SW_BUILD_DIR)/%.o: $(LIB_DIR)/$$*.S
+	$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
+
+$(SW_BUILD_DIR)/%.ppo: $(LIB_DIR)/$$*.c
+	$(CC) $(CFLAGS) -E -MMD -c $(INCS) -o $@ $<
+
+$(SW_BUILD_DIR)/%.ppo: $(LIB_DIR)/$$*.S
+	$(CC) $(CFLAGS) -E -MMD -c $(INCS) -o $@ $<
+
+$(SW_BUILD_DIR)/%.o: $(EXT_COMMON_DIR)/$$*.c
+	$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
+
+$(SW_BUILD_DIR)/%.o: $(EXT_COMMON_DIR)/$$*.S
+	$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
+
+$(SW_BUILD_DIR)/%.ppo: $(EXT_COMMON_DIR)/$$*.c
+	$(CC) $(CFLAGS) -E -MMD -c $(INCS) -o $@ $<
+
+$(SW_BUILD_DIR)/%.ppo: $(EXT_COMMON_DIR)/$$*.S
+	$(CC) $(CFLAGS) -E -MMD -c $(INCS) -o $@ $<
+
+# compile lib sources
+$(LIB_BUILD_DIR)/%.o: $(LIB_DIR)/$$*.c
+	$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
+
+$(LIB_BUILD_DIR)/%.o: $(LIB_DIR)/$$*.S
+	$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
+
+$(LIB_BUILD_DIR)/%.ppo: $(LIB_DIR)/$$*.c
+	$(CC) $(CFLAGS) -E -MMD -c $(INCS) -o $@ $<
+
+$(LIB_BUILD_DIR)/%.ppo: $(LIB_DIR)/$$*.S
+	$(CC) $(CFLAGS) -E -MMD -c $(INCS) -o $@ $<
+
+$(LIB_BUILD_DIR)/%.o: $(EXT_COMMON_DIR)/$$*.c
+	$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
+
+$(LIB_BUILD_DIR)/%.o: $(EXT_COMMON_DIR)/$$*.S
+	$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
+
+$(LIB_BUILD_DIR)/%.ppo: $(EXT_COMMON_DIR)/$$*.c
+	$(CC) $(CFLAGS) -E -MMD -c $(INCS) -o $@ $<
+
+$(LIB_BUILD_DIR)/%.ppo: $(EXT_COMMON_DIR)/$$*.S
+	$(CC) $(CFLAGS) -E -MMD -c $(INCS) -o $@ $<
+
+# regtool
+$(LIB_BUILD_DIR)/%_regs.h: $(SW_ROOT_DIR)/../hw/ip/$$*/doc/$$*.hjson
+	$(REGTOOL) -D -o $@ $<
+
+$(LIB_BUILD_DIR)/%_regs.h: $(SW_ROOT_DIR)/../hw/ip/$$*/doc/$$*_regs.hjson
+	$(REGTOOL) -D -o $@ $<
+
+# chip_info
+$(LIB_BUILD_DIR)/chip_info.h: $(INFOTOOL)
+	$(INFOTOOL) -o $(LIB_BUILD_DIR)
+
+-include $(DEPS)
+
+# clean sources
+clean:
+	-$(RM) -r $(LIB_OBJS) $(LIB_PPOS) $(SW_OBJS) $(SW_PPOS) $(DEPS) \
+	          $(GEN_HEADER_OUTPUTS) $(IMG_OUTPUTS) $(LIB_TARGET) ${SW_BUILD_DIR}/env_vars
+
+distclean: clean
+
+.PHONY: gen_dir lib clean distclean standalone
diff --git a/sw/tests/flash_ctrl/Makefile b/sw/tests/flash_ctrl/Makefile
deleted file mode 100644
index 6f595dd..0000000
--- a/sw/tests/flash_ctrl/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-#
-# Generate a baremetal application for the microcontroller
-
-NAME         = flash_test
-SRCS         = flash_test.c
-PROGRAM_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
-
-include ${PROGRAM_DIR}/../../exts/common/options.mk
-include ${PROGRAM_DIR}/../../exts/common/common.mk
diff --git a/sw/tests/flash_ctrl/srcs.mk b/sw/tests/flash_ctrl/srcs.mk
new file mode 100644
index 0000000..c1be2b8
--- /dev/null
+++ b/sw/tests/flash_ctrl/srcs.mk
@@ -0,0 +1,10 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+SW_NAME       ?= flash_test
+
+# list srcs for each test
+ifeq ($(SW_NAME), flash_test)
+  SW_SRCS     += $(SW_DIR)/flash_test.c
+endif
diff --git a/sw/tests/hmac/Makefile b/sw/tests/hmac/Makefile
deleted file mode 100644
index 61f3e40..0000000
--- a/sw/tests/hmac/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-#
-# Generate a baremetal application for the microcontroller
-
-NAME         = sha256_test
-SRCS         = sha256_test.c
-PROGRAM_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
-
-include ${PROGRAM_DIR}/../../exts/common/options.mk
-include ${PROGRAM_DIR}/../../exts/common/common.mk
diff --git a/sw/tests/hmac/srcs.mk b/sw/tests/hmac/srcs.mk
new file mode 100644
index 0000000..3e62103
--- /dev/null
+++ b/sw/tests/hmac/srcs.mk
@@ -0,0 +1,12 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+SW_NAME       ?= sha256_test
+INCS          += -I$(SW_ROOT_DIR)/vendor
+
+# list srcs for each test
+ifeq ($(SW_NAME), sha256_test)
+  SW_SRCS     += $(SW_DIR)/sha256_test.c
+  SW_SRCS     += $(LIB_DIR)/hw_sha256.c
+endif
diff --git a/sw/tests/rv_timer/Makefile b/sw/tests/rv_timer/Makefile
deleted file mode 100644
index 22e926c..0000000
--- a/sw/tests/rv_timer/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-#
-# Generate a baremetal application for the microcontroller
-
-NAME         = rv_timer_test
-SRCS         = rv_timer_test.c
-PROGRAM_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
-
-include ${PROGRAM_DIR}/../../exts/common/options.mk
-include ${PROGRAM_DIR}/../../exts/common/common.mk
diff --git a/sw/tests/rv_timer/srcs.mk b/sw/tests/rv_timer/srcs.mk
new file mode 100644
index 0000000..fb7651c
--- /dev/null
+++ b/sw/tests/rv_timer/srcs.mk
@@ -0,0 +1,10 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+SW_NAME       ?= rv_timer_test
+
+# list srcs for each test
+ifeq ($(SW_NAME), rv_timer_test)
+  SW_SRCS     += $(SW_DIR)/rv_timer_test.c
+endif