Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/scripts/check_sim.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
LOG_FILE=$1

expected_lines=(
"\[CORE\] Start fetching instructions"
"\[CORE\] Waking core via CLINT msip"
"\[JTAG\] Halting hart 0"
"\[JTAG\] Resumed hart 0"
"\[UART\] Hello World!"
Expand Down
1 change: 1 addition & 0 deletions Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ sources:
files:
# Level 1
- rtl/core_wrap.sv
- rtl/bootrom/bootrom.sv
- rtl/soc_ctrl/soc_ctrl_regs.sv
- rtl/gpio/gpio_reg_top.sv
- rtl/gpio/gpio.sv
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ The address map of the default configuration is as follows:
| Start Address | Stop Address | Description |
|-----------------|-----------------|--------------------------------------------|
| `32'h0000_0000` | `32'h0004_0000` | Debug module (JTAG) |
| `32'h0200_0000` | `32'h0200_4000` | Bootrom |
| `32'h0200_4000` | `32'h0200_8000` | CLINT peripheral |
| `32'h0300_0000` | `32'h0300_1000` | SoC control/info registers |
| `32'h0300_2000` | `32'h0300_3000` | UART peripheral |
| `32'h0300_5000` | `32'h0300_6000` | GPIO peripheral |
Expand All @@ -62,7 +64,6 @@ The address map of the default configuration is as follows:
| `32'h2000_0000` | `32'h8000_0000` | Passthrough to user domain |
| `32'h2000_0000` | `32'h2000_1000` | reserved for string formatted user ROM* |


*If people modify Croc we suggest they add a ROM at this address containing additional information
like the names of the developers, a project link or similar. This can then be written out via UART.
We ask people to format the ROM like a C string with zero termination and using ASCII encoding if feasible.
Expand Down
8 changes: 4 additions & 4 deletions artistic/src/croc.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
"file" : "../meerkat_work/croc_chip.gds.gz",
"x_offset_um" : 0,
"y_offset_um" : 0,
"width_um" : 1930,
"height_um" : 1930
"width_um" : 2000,
"height_um" : 2000
},
"image": {
"px_width" : 965,
"px_height" : 965,
"px_width" : 1000,
"px_height" : 1000,
"overrender_factor" : 4,
"num_segs_width" : 1,
"num_segs_height" : 1,
Expand Down
4 changes: 2 additions & 2 deletions artistic/src/croc_map.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
},
"gds" : {
"file" : "../meerkat_work/croc_chip.gds.gz",
"x_offset_um" : -59,
"y_offset_um" : -59,
"x_offset_um" : -24,
"y_offset_um" : -24,
"width_um" : 2048,
"height_um" : 2048
},
Expand Down
4 changes: 4 additions & 0 deletions artistic/src/croc_modules.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
"name": "GPIO",
"color": "#43fdaa"
},
"i_bootrom": {
"name": "ROM",
"color": "#8cf805"
},
"gen_sram_bank": {
"name": "SRAM",
"color": "#39729f"
Expand Down
4 changes: 2 additions & 2 deletions openroad/scripts/init_tech.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ proc setDefaultParasitics {} {
}

# Tie cell pins
set tieHiPin "TIEHI/Y"
set tieLoPin "TIELO/Y"
set tieHiPin "sg13g2_tiehi/L_HI"
set tieLoPin "sg13g2_tielo/L_LO"

# Tap cell insertion
proc insertTapCells {} {
Expand Down
10 changes: 5 additions & 5 deletions openroad/src/constraints.sdc
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ set_max_delay 3.0 -from $JTAG_ASYNC_RSP_START -to $JTAG_ASYNC_RSP_END -ignore_cl
puts "Input/Outputs..."

# Reset should propagate to system domain within a clock cycle.
set_input_delay -max [ expr $TCK_JTG * 0.10 ] [get_ports rst_ni]
set_false_path -hold -from [get_ports rst_ni]
set_max_delay $TCK_SYS -from [get_ports rst_ni]
set_input_delay -max [ expr $TCK_JTG * 0.10 ] [get_ports {rst_ni testmode_i}]
set_false_path -hold -from [get_ports {rst_ni testmode_i}]
set_max_delay $TCK_SYS -from [get_ports {rst_ni testmode_i}]


##########
Expand All @@ -109,8 +109,8 @@ set_max_delay $TCK_JTG -from [get_ports jtag_trst_ni]
##########
puts "GPIO..."

set_input_delay -min -add_delay -clock clk_sys [ expr $TCK_SYS * 0.10 ] [get_ports {gpio* fetch_en_i}]
set_input_delay -max -add_delay -clock clk_sys [ expr $TCK_SYS * 0.30 ] [get_ports {gpio* fetch_en_i}]
set_input_delay -min -add_delay -clock clk_sys [ expr $TCK_SYS * 0.10 ] [get_ports {gpio*}]
set_input_delay -max -add_delay -clock clk_sys [ expr $TCK_SYS * 0.30 ] [get_ports {gpio*}]

set_output_delay -min -add_delay -clock clk_sys [ expr $TCK_SYS * 0.10 ] [get_ports {gpio*}]
set_output_delay -max -add_delay -clock clk_sys [ expr $TCK_SYS * 0.30 ] [get_ports {gpio*}]
Expand Down
2 changes: 1 addition & 1 deletion openroad/src/padring.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ place_pad -row IO_WEST -location [expr {$westStart - 0*$westPitch}] "pad_vssio0
place_pad -row IO_WEST -location [expr {$westStart - 1*$westPitch}] "pad_vddio0" ; # pin no: 2
place_pad -row IO_WEST -location [expr {$westStart - 2*$westPitch}] "pad_uart_rx_i" ; # pin no: 3
place_pad -row IO_WEST -location [expr {$westStart - 3*$westPitch}] "pad_uart_tx_o" ; # pin no: 4
place_pad -row IO_WEST -location [expr {$westStart - 4*$westPitch}] "pad_fetch_en_i" ; # pin no: 5
place_pad -row IO_WEST -location [expr {$westStart - 4*$westPitch}] "pad_testmode_i" ; # pin no: 5
place_pad -row IO_WEST -location [expr {$westStart - 5*$westPitch}] "pad_status_o" ; # pin no: 6
place_pad -row IO_WEST -location [expr {$westStart - 6*$westPitch}] "pad_clk_i" ; # pin no: 7
place_pad -row IO_WEST -location [expr {$westStart - 7*$westPitch}] "pad_ref_clk_i" ; # pin no: 8
Expand Down
4 changes: 4 additions & 0 deletions rtl/bootrom/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bootrom.bin
bootrom.dump
bootrom.elf
bootrom.o
154 changes: 154 additions & 0 deletions rtl/bootrom/bootrom.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Copyright (c) 2026 ETH Zurich and University of Bologna.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# Authors:
# - Philippe Sauter <phsauter@iis.ee.ethz.ch>
#
# Bootrom for the Croc SoC
# Located at 0x0200_0000
#
# Boot flow:
# 1. Enable MSIE, WFI (wait until woken by JTAG via msip)
# 2. Wake: clear msip, disable interrupts
# 3. Clear registers x1, x3-x15 (x2/SP set by SRAM stub)
# 4. Set mtvec to bootrom trap handler
# 5. Read boot address from soc_ctrl, jump there with jalr zero
# (ra is set to &_eoc so main() returning goes to _eoc)
# 6. _eoc: pack return value, write CORESTATUS, WFI
#
# Trap handling:
# The bootrom trap handler saves/restores caller-saved registers and dispatches
# to user handlers via a function pointer vector table at fixed addresses:
# - 0x1000_0000: j _start (skip table)
# - 0x1000_0004: .word croc_exception_handler (function pointer)
# - 0x1000_0008: .word croc_interrupt_handler (function pointer)
#
# Fixed section offsets (from base 0x0200_0000):
# 0x000 _start (WFI trampoline + boot)
# 0x100 _eoc (end of computation)
# 0x200 _trap_handler_wrapper (trap entry, save regs, dispatch)
# 0x300 _trap_exit (restore regs, mret)

# -----------------------------------------------------------------------------
# WFI Trampoline (entry point after reset)
# -----------------------------------------------------------------------------
.section .text
.globl _start
_start:
csrwi mie, 8 # Enable M-mode software interrupt
wfi # Sleep until interrupt
lui t0, 0x02040 # t0 = CLINT base (0x0204_0000)
sw zero, 0(t0) # Clear msip
csrwi mie, 0 # Disable all interrupts

# -----------------------------------------------------------------------------
# Register Initialization
# Clear x1, x3-x15. Skip x2 stack pointer, set by main sw (needs SRAM size)
# -----------------------------------------------------------------------------
# addi x1, zero, 0 # x1 is ra, used later, so we can skip clearing it
# addi x2, zero, 0 # x2 is sp, set by SRAM stub, so we can skip clearing it
addi x3, zero, 0
addi x4, zero, 0
# addi x5, zero, 0 # x5 is t0, used later, so we can skip clearing it
addi x6, zero, 0
addi x7, zero, 0
addi x8, zero, 0
addi x9, zero, 0
addi x10, zero, 0
addi x11, zero, 0
addi x12, zero, 0
addi x13, zero, 0
addi x14, zero, 0
addi x15, zero, 0

# -----------------------------------------------------------------------------
# CSR Initialization
# Set mtvec to bootrom trap handler
# -----------------------------------------------------------------------------
la t0, _trap_handler_wrapper
csrw mtvec, t0

# -----------------------------------------------------------------------------
# Boot software
# Read address from soc_ctrl register and jump
# -----------------------------------------------------------------------------
lui t0, 0x03000 # t0 = SOC_CTRL base (0x0300_0000)
lw t0, 0(t0) # t0 = boot address (BOOTADDR register)
la ra, _eoc # ra = &_eoc (return address for main)
jalr zero, 0(t0) # Jump to boot address (rd=zero, ra preserved)

# -----------------------------------------------------------------------------
# End of Computation (_eoc)
# Reached when main() returns (via ra set above)
# Pack return value and write to CORESTATUS register
# -----------------------------------------------------------------------------
.org 0x100
.globl _eoc
_eoc:
slli t0, a0, 1 # Shift return code left by 1
ori t0, t0, 1 # Set bit 0 (EOC flag)
lui t1, 0x03000 # t1 = SOC_CTRL base (0x0300_0000)
sw t0, 8(t1) # Write to CORESTATUS (offset 0x08)
wfi # Halt

# -----------------------------------------------------------------------------
# Trap Handler Wrapper
# Saves caller-saved registers, reads mcause,
# dispatches to interrupt/exception handler in SRAM via function pointer table
# -----------------------------------------------------------------------------
.org 0x200
_trap_handler_wrapper:
addi sp, sp, -80
sw ra, 72(sp)
sw t0, 64(sp)
sw t1, 56(sp)
sw t2, 48(sp)
sw a0, 40(sp)
sw a1, 32(sp)
sw a2, 24(sp)
sw a3, 16(sp)
sw a4, 8(sp)
sw a5, 0(sp)

# Read trap cause
# mcause[31] == 1 -> Interrupt
# mcause[31] == 0 -> Exception
lui t0, 0x10000 # t0 = SRAM base (0x1000_0000)
csrr a0, mcause
blt a0, zero, _handle_interrupt

# Exception: call handler via SRAM vector table
lw t1, 4(t0) # t1 = *(0x1000_0004)
jalr ra, 0(t1) # Call exception handler
j _trap_exit

# -----------------------------------------------------------------------------
# Interrupt Handler
# Strips mcause MSB to get interrupt ID, dispatches to user handler in SRAM
# -----------------------------------------------------------------------------
_handle_interrupt:
slli a0, a0, 1 # Strip MSB (shift left)
srli a0, a0, 1 # Restore (shift right) -> a0 = interrupt ID
lw t1, 8(t0) # t1 = *(0x1000_0008)
jalr ra, 0(t1) # Call interrupt handler
j _trap_exit

# -----------------------------------------------------------------------------
# Trap Exit
# Restore caller-saved registers and return from trap
# -----------------------------------------------------------------------------
.org 0x300
_trap_exit:
lw ra, 72(sp)
lw t0, 64(sp)
lw t1, 56(sp)
lw t2, 48(sp)
lw a0, 40(sp)
lw a1, 32(sp)
lw a2, 24(sp)
lw a3, 16(sp)
lw a4, 8(sp)
lw a5, 0(sp)
addi sp, sp, 80
mret
Loading
Loading