3. Building the Core

The code is hosted on Gitlab and can be checked out using the following command:

$ git clone https://gitlab.incoresemi.com/core-generators/chromite.git

If you are cloning the chromite repo for the first time it would be best to install the dependencies first:

$ cd chromite/
$ pyenv activate venv # ignore this is you are not using pyenv
$ pip install -U -r requirements.txt

The Chromite core generator takes a specific YAML format as input. It makes specific checks to validate if the user has entered valid data and none of the parameters conflict with each other. For e.g., mentioning the ‘D’ extension without the ‘F’ will get captured by the generator as an invalid spec. More information on the exact parameters and constraints on each field are discussed here.

Once the input YAML has been validated, the generator then clones all the dependent repositories which enable building a test-soc, simulating it and performing verification of the core. This is an alternative to maintaining the repositories as submodules, which typically pollutes the commit history with bump commits.

At the end, the generator outputs a single makefile.inc in the same folder that it was run, which contains definitions of paths where relevant bluespec files are present, bsc command with macro definitions, verilator simulation commands, etc.

A sample yaml input YAML (default.yaml) is available in the sample_config directory of the repository.

In this guide we will be building the core along with a sample test-soc which includes some basic peripherals to run sample applications. We also include a test-bench for the test-soc and the entire design has the following hierarchy structure (defined to a max of 5 levels of depth):

graph TD; X[mkTbSoC] --> A(mkSoC) X --> B(mkbram) X --> C(mkbootrom) A --> D(mkchromite_axi4) A --> E(mkuart) A --> F(mkclint) A --> G(mksignature_dump) D --> H(mkriscv) D --> I(mkdmem) D --> J(mkimem) J --> K(mkicache) J --> L(mkitlb*) I --> M(mkdcache) I --> N(mkdtlb*)

Description of the above modules:

Module-Name

Description

mkriscv

Contains the stages of the core pipeline including the ALU units and only the interface to the memory subsystem

mkdmem

The Data memory subsystem. Includes the data-cache and data-tlbs

mkimem

The instruction memory subsystem. Includes the instruction-cache and the instruction-tlbs

mkchromite_axi4

Contains the above modules and the integrations across them. Also provides 2 AXI-4 interfaces to be connected to the Cross-bar fabric

mkuart

UART module

mkclint

Core Level Interrupt

mksignature_dump

Signature dump module (for simulation only)

mkSoc

contains all the above modules and instantiates the AXI-4 crossbar fabric as well. The fabric has 2 additional slaves, which are brought out through the interface to connect to the boot-rom and bram-main-memory present in the Test-bench

mkbram

BRAM based memory acting as main-memory

mkbootrom

Bootrom slave

mkTbSoC

Testbench that instantiates the Soc, and integrates it with the bootrom and a bram memory

The details of the devices can be found in devices

3.1. Address Map of Test SoC

Module

Address Range

BRAM-Memory

0x80000000 - 0x8FFFFFFF

BootROM

0x00001000 - 0x00010FFF

UART

0x00011300 - 0x00011340

CLINT

0x02000000 - 0x020BFFFF

Debug-Halt Loop

0x00000000 - 0x0000000F

Signature Dump

0x00002000 - 0x0000200c

To build the core with a sample test-soc we need to provide a few yaml configuration files as listed below:

  • isa.yaml : the riscv-config yaml capturing the ISA configurations of the core

  • custom.yaml: yaml capturing any chromite specific csrs (see riscv-config itself)

  • core.yaml: capturing all the micro-architecture specific configurations (see Section 5)

  • csr_grouping.yaml: capturing the csr grouping file required by csrbox

  • debug.yaml: captures all the debug related features

The Chromite repo provides a few sample configurations in the sample_configs directory at the root level and we will use the rv64imacsu config as follows:

$ python -m configure.main -ispec sample_config/rv64imacsu/isa.yaml
  -customspec sample_config/rv64imacsu/custom.yaml -cspec sample_config/rv64imacsu/core.yaml
  -gspec sample_config/rv64imacsu/csr_grouping.yaml
  -dspec sample_config/rv64imacsu/debug.yaml --verbose debug

The above step generates a makefile.inc file in the same folder and also clones other dependent repositories to build a test-soc and carry out verification. This should generate a log something similar to:

[INFO]    : ************ Chromite Core Generator ************
[INFO]    : ------ Copyright (c) InCore Semiconductors ------
[INFO]    : ---------- Available under BSD License----------
[INFO]    :


[INFO]    : Checking pre-requisites
[INFO]    : Cloning "cache_subsystem" from URL "https://gitlab.incoresemi.com/blocks/cache_subsystem"
[INFO]    : Checking out "1.0.0" for repo "cache_subsystem"
[INFO]    : Cloning "common_bsv" from URL "https://gitlab.incoresemi.com/blocks/common_bsv"
[INFO]    : Checking out "master" for repo "common_bsv"
[INFO]    : Cloning "fabrics" from URL "https://gitlab.incoresemi.com/blocks/fabrics"
[INFO]    : Checking out "1.1.1" for repo "fabrics"
[INFO]    : Cloning "bsvwrappers" from URL "https://gitlab.incoresemi.com/blocks/bsvwrappers"
[INFO]    : Checking out "master" for repo "bsvwrappers"
[INFO]    : Cloning "devices" from URL "https://gitlab.incoresemi.com/blocks/devices"
[INFO]    : Checking out "1.0.0" for repo "devices"
[INFO]    : Cloning "benchmarks" from URL "https://gitlab.incoresemi.com/core-generators/benchmarks"
[INFO]    : Checking out "master" for repo "benchmarks"
[INFO]    : Loading input file: /scratch/git-repo/incoresemi/core-generators/chromite/sample_config/default.yaml
[INFO]    : Load Schema configure/schema.yaml
[INFO]    : Initiating Validation
[INFO]    : No Syntax errors in Input Yaml.
[INFO]    : Performing Specific Checks
[INFO]    : Generating BSC compile options
[INFO]    : makefile.inc generated
[INFO]    : Creating Dependency graph
[WARNING] : path: .:%/Libraries:src/:src/predictors:src/m_ext:src/fpu/:src/m_ext/..........
defines: Addr_space=25 ASSERT rtldump RV64 ibuswidth=64 dbuswidth=64 .......
builddir: build/hw/intermediate
topfile: test_soc/TbSoc.bsv
outputfile: depends.mk
argv:
generated make dependency rules for "test_soc/TbSoc.bsv" in: depends.mk
[INFO]    : Dependency Graph Created
[INFO]    : Cleaning previously built code
[WARNING] : rm -rf build/hw/intermediate/* *.log bin/* obj_dir build/hw/verilog/*
rm -f *.jou rm *.log *.mem log sim_main.h cds.lib hdl.var
[INFO]    : Run make -j<jobs>

To compile the bluespec source and generate verilog

$ make -j<jobs> generate_verilog

If you are using the samples/default.yaml config file, this should generate the following folders:

  1. build/hw/verilog: contains the generated verilog files.

  2. build/hw/intermediate: contains all the intermediate and information files generated by bsc.

Congratulations - You have built your very first Chromite core !! :)

3.2. Building just the core

For integration in a separate SoC, or advanced simulations or synthesis, it might be required to just generate the core instance alone without any of the other collaterals (uart, clint, etc). To do this the procedure is the same as above except the following changes to be done in the core.yaml fields:

bsc_compile_options:
  trace_dump: false
  top_module: mkchromite_axi4
  top_file: chromite.bsv
  top_dir: src

The top level module will be mkchromite_axi4 in the file build/hw/verilog/mkchromite_axi4.v. This module has the following port map

Signal name

Direction

Size

Description

resetpc

Input

64

indicates the program counter value once reset is deasserted

CLK

Input

1

core clock

RST_N

Input

1

core reset (active low)

master_d_AWREADY

Input

1

AXI4 Master interface signals for the Data-Cache

master_d_WREADY

Input

1

master_d_BVALID

Input

1

master_d_BID

Input

1

master_d_BRESP

Input

2

master_d_ARREADY

Input

1

master_d_RVALID

Input

1

master_d_RID

Input

1

master_d_RDATA

Input

64

master_d_RRESP

Input

2

master_d_RLAST

Input

1

master_i_AWREADY

Input

1

AXI4 Master interface signals for the Instruction-Cache

master_i_WREADY

Input

1

master_i_BVALID

Input

1

master_i_BID

Input

1

master_i_BRESP

Input

2

master_i_ARREADY

Input

1

master_i_RVALID

Input

1

master_i_RID

Input

1

master_i_RDATA

Input

64

master_i_RRESP

Input

2

master_i_RLAST

Input

1

sb_clint_msip_m

Input

1

machine software interrupt from clint

sb_clint_mtip_m

Input

1

machine timer interrupt from clint

sb_clint_mtime_m

Input

64

machine mtime value from clint

sb_plic_meip_ex_i

Input

1

machine external interrupt from plic

sb_plic_seip_ex_i

Input

1

supervisor external interrupt from plic

ma_debug_interrupt__int

Input

1

interrupt indicating debugger requesting a halt

ma_debugger_available_avail

Input

1

single bit indicating if debugger is connected

master_d_AWVALID

Output

1

AXI4 Master interface signals for the Data-Cache

master_d_AWID

Output

1

master_d_AWADDR

Output

32

master_d_AWLEN

Output

8

master_d_AWSIZE

Output

3

master_d_AWBURST

Output

2

master_d_AWLOCK

Output

1

master_d_AWCACHE

Output

4

master_d_AWPROT

Output

3

master_d_AWQOS

Output

4

master_d_AWREGION

Output

4

master_d_WVALID

Output

1

master_d_WDATA

Output

64

master_d_WSTRB

Output

8

master_d_WLAST

Output

1

master_d_BREADY

Output

1

master_d_ARVALID

Output

1

master_d_ARID

Output

1

master_d_ARADDR

Output

32

master_d_ARLEN

Output

8

master_d_ARSIZE

Output

3

master_d_ARBURST

Output

2

master_d_ARLOCK

Output

1

master_d_ARCACHE

Output

4

master_d_ARPROT

Output

3

master_d_ARQOS

Output

4

master_d_ARREGION

Output

4

master_d_RREADY

Output

1

master_i_AWVALID

Output

1

AXI4 Master interface signals for the Data-Cache

master_i_AWID

Output

1

master_i_AWADDR

Output

32

master_i_AWLEN

Output

8

master_i_AWSIZE

Output

3

master_i_AWBURST

Output

2

master_i_AWLOCK

Output

1

master_i_AWCACHE

Output

4

master_i_AWPROT

Output

3

master_i_AWQOS

Output

4

master_i_AWREGION

Output

4

master_i_WVALID

Output

1

master_i_WDATA

Output

64

master_i_WSTRB

Output

8

master_i_WLAST

Output

1

master_i_BREADY

Output

1

master_i_ARVALID

Output

1

master_i_ARID

Output

1

master_i_ARADDR

Output

32

master_i_ARLEN

Output

8

master_i_ARSIZE

Output

3

master_i_ARBURST

Output

2

master_i_ARLOCK

Output

1

master_i_ARCACHE

Output

4

master_i_ARPROT

Output

3

master_i_ARQOS

Output

4

master_i_ARREGION

Output

4

master_i_RREADY

Output

1

mv_core_is_reset

Output

1

indicates that the core is out of reset

mv_core_debugenable

Output

1

indicates that the core is available for debug

mv_stop_timer

Output

1

indicates that the clint should stop incrementing timer

mv_stop_count

Output

1

indicates that all performance counters must be stoped