├── sw ├── devices.h ├── .gitignore ├── test.s ├── entry.s ├── lib │ ├── zerosoc.h │ └── zerosoc.c ├── Makefile ├── hello.c └── ram.ld ├── sim ├── .gitignore └── zerosoc_tb.v ├── hw ├── asic_top.sdc ├── pad.v ├── prim │ ├── ice40 │ │ └── prim_ice40_clock_gating.v │ ├── lambdalib │ │ ├── prim_lambdalib_clock_gating.v │ │ └── prim_lambdalib_ram_1p.v │ ├── prim_pkg.sv │ ├── README.md │ ├── prim_clock_inv.sv │ ├── prim_clock_buf.sv │ ├── prim_flop_2sync.sv │ ├── prim_buf.sv │ ├── prim_xor2.sv │ ├── prim_pad_attr.sv │ ├── prim_rom.sv │ ├── prim_clock_mux2.sv │ ├── prim_usb_diff_rx.sv │ ├── prim_flop.sv │ ├── prim_flop_en.sv │ ├── prim_clock_gating.sv │ ├── prim_ram_2p.sv │ ├── prim_pad_wrapper.sv │ ├── prim_ram_1p.sv │ ├── prim_flash.sv │ └── prim_otp.sv ├── SB_HFOSC.v ├── xbar_pkg.sv ├── top_icebreaker.v ├── iomap.vh ├── tl_dbg.sv ├── xbar.sv ├── asic_top.v ├── zerosoc.sv ├── asic_core.v └── uart_core.sv ├── docs ├── img │ └── zerosoc.png ├── memorymap.md └── fpga.md ├── .flake8 ├── python-requirements.txt ├── openroad ├── global_connect_io.tcl ├── pdngen_core.tcl ├── pdngen_sram.tcl ├── global_connect_core_top.tcl ├── global_connect_core.tcl ├── global_connect_core_top_flat.tcl ├── pdngen_core_only.tcl ├── pdngen_top.tcl └── padring.tcl ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── zerosoc_top.py ├── Makefile ├── zerosoc_core.py ├── fpga └── icebreaker.pcf ├── README.md ├── opentitan.py ├── floorplan.py ├── LICENSE ├── make.py └── random.mem /sw/devices.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sim/.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | -------------------------------------------------------------------------------- /sw/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.elf 3 | *.bin 4 | *.mem 5 | gen/ -------------------------------------------------------------------------------- /hw/asic_top.sdc: -------------------------------------------------------------------------------- 1 | create_clock -period 66 -name clk [get_port we_pad[5]] 2 | -------------------------------------------------------------------------------- /docs/img/zerosoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siliconcompiler/zerosoc/HEAD/docs/img/zerosoc.png -------------------------------------------------------------------------------- /sw/test.s: -------------------------------------------------------------------------------- 1 | .global _reset 2 | .type _reset, %function 3 | _reset: 4 | addi x1, x1, 1 5 | jal x0, _reset 6 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | extend-exclude = opentitan,oh,.venv 3 | max-complexity = 10 4 | max-line-length = 100 5 | -------------------------------------------------------------------------------- /python-requirements.txt: -------------------------------------------------------------------------------- 1 | bin2coe 2 | hjson 3 | mako 4 | siliconcompiler >= 0.25.0 5 | lambdapdk >= 0.2.0 6 | lambdalib >= 0.4.0 7 | -------------------------------------------------------------------------------- /hw/pad.v: -------------------------------------------------------------------------------- 1 | module pad ( 2 | input out_i, 3 | input oe_i, 4 | output in_o, 5 | 6 | inout inout_io 7 | ); 8 | assign in_o = inout_io; 9 | assign inout_io = oe_i ? out_i : 1'bz; 10 | endmodule 11 | -------------------------------------------------------------------------------- /openroad/global_connect_io.tcl: -------------------------------------------------------------------------------- 1 | #################################### 2 | # global connections 3 | #################################### 4 | add_global_connection -net {vddio} -pin_pattern {VDDIO} -power 5 | add_global_connection -net {vssio} -pin_pattern {VSSIO} -ground 6 | -------------------------------------------------------------------------------- /openroad/pdngen_core.tcl: -------------------------------------------------------------------------------- 1 | #################################### 2 | # grid for: core 3 | #################################### 4 | define_pdn_grid -name {chip_core} -voltage_domains {CORE} -macro -cells "asic*" -halo "1.0 1.0 1.0 1.0" 5 | add_pdn_connect -grid {chip_core} -layers {met4 met5} 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "weekly" 8 | groups: 9 | actions: 10 | patterns: 11 | - "*" 12 | -------------------------------------------------------------------------------- /openroad/pdngen_sram.tcl: -------------------------------------------------------------------------------- 1 | #################################### 2 | # grid for: sky130_sram_* 3 | #################################### 4 | define_pdn_grid -name {SRAM} -voltage_domains {CORE} -macro -cells "sky130_sram_*" -halo "2.0 2.0 2.0 2.0" 5 | add_pdn_connect -grid {SRAM} -layers {met3 met4} 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | zerosoc.v 2 | zerosoc.vcd 3 | 4 | # SC build dir 5 | build/ 6 | *.json 7 | .venv/ 8 | 9 | # FPGA build outputs 10 | *.asc 11 | *.bit 12 | 13 | # ASIC build outputs 14 | asic_core.gds 15 | asic_core.def 16 | asic_core.lef 17 | asic_core.vg 18 | asic_top.def 19 | 20 | # Python build cache 21 | __pycache__/ 22 | 23 | # Stuff generated from tutorial template 24 | zerosoc.rst 25 | -------------------------------------------------------------------------------- /hw/prim/ice40/prim_ice40_clock_gating.v: -------------------------------------------------------------------------------- 1 | module prim_ice40_clock_gating #( 2 | parameter bit NoFpgaGate = 1'b0 3 | ) ( 4 | input clk_i, 5 | input en_i, 6 | input test_en_i, 7 | output logic clk_o 8 | ); 9 | 10 | // TODO: can implement a proper clock gate using SB_GB_IO primitive 11 | 12 | assign clk_o = clk_i; 13 | 14 | endmodule 15 | -------------------------------------------------------------------------------- /hw/SB_HFOSC.v: -------------------------------------------------------------------------------- 1 | // Dummy shim for Lattice primitive to prevent Verilator lint from throwing an 2 | // error. Yosys synthesis will replace this implementation with the proper cell. 3 | 4 | module SB_HFOSC #( 5 | // Fixed width ensures that sv2v doesn't insert an extra string width 6 | // parameter when converting top-level 7 | parameter [31:0] CLKHF_DIV = "0b11" 8 | ) ( 9 | input CLKHFPU, 10 | input CLKHFEN, 11 | output CLKHF 12 | ); 13 | 14 | endmodule 15 | -------------------------------------------------------------------------------- /hw/xbar_pkg.sv: -------------------------------------------------------------------------------- 1 | package xbar_pkg; 2 | 3 | localparam logic [31:0] ADDR_SPACE_RAM = 32'h 00000000; 4 | localparam logic [31:0] ADDR_SPACE_UART = 32'h 40000000; 5 | localparam logic [31:0] ADDR_SPACE_GPIO = 32'h 40010000; 6 | 7 | localparam logic [31:0] ADDR_MASK_RAM = 32'h 00001fff; 8 | localparam logic [31:0] ADDR_MASK_UART = 32'h 00000fff; 9 | localparam logic [31:0] ADDR_MASK_GPIO = 32'h 00000fff; 10 | 11 | endpackage 12 | -------------------------------------------------------------------------------- /docs/memorymap.md: -------------------------------------------------------------------------------- 1 | # Memory map 2 | 3 | Putting this here as a single source of truth between `hw/xbar_pkg.sv` and 4 | `sw/devices.h`. Having a generator for these files could be useful! 5 | 6 | (These addresses are based on the addresses used in OpenTitan, but can be 7 | changed/finalized once full set of peripherals is complete) 8 | 9 | Peripheral | Base Address 10 | -----------|------------- 11 | RAM | 0x00000000 12 | UART | 0x40000000 13 | GPIO | 0x40010000 14 | 15 | -------------------------------------------------------------------------------- /hw/prim/lambdalib/prim_lambdalib_clock_gating.v: -------------------------------------------------------------------------------- 1 | module prim_lambdalib_clock_gating #( 2 | parameter bit NoFpgaGate = 1'b0 3 | ) ( 4 | input clk_i, 5 | input en_i, 6 | input test_en_i, 7 | output logic clk_o 8 | ); 9 | 10 | // sky130_fd_sc_hd__dlclkp_1 latch (.CLK (clk_i), .GATE(en_i | test_en_i), .GCLK(clk_o)); 11 | 12 | // We've noticed issues with OpenROAD CTS's handling of clock gates, so hardcode 13 | // a passthru for now. 14 | assign clk_o = clk_i; 15 | 16 | endmodule 17 | -------------------------------------------------------------------------------- /zerosoc_top.py: -------------------------------------------------------------------------------- 1 | import os 2 | from siliconcompiler import Library 3 | from lambdalib import padring 4 | import zerosoc_core 5 | 6 | 7 | def setup(): 8 | lib = Library('zerosoc_top', package='zerosoc', auto_enable=True) 9 | lib.register_source( 10 | name='zerosoc', 11 | path=os.path.abspath(os.path.dirname(__file__))) 12 | 13 | lib.input('hw/asic_top.v') 14 | lib.add('option', 'idir', 'hw') 15 | 16 | lib.use(padring) 17 | lib.use(zerosoc_core) 18 | 19 | return lib 20 | -------------------------------------------------------------------------------- /hw/prim/prim_pkg.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | // 5 | // Constants for use in primitives 6 | 7 | // This file is auto-generated. 8 | 9 | package prim_pkg; 10 | 11 | // Implementation target specialization 12 | typedef enum integer { 13 | ImplGeneric, 14 | ImplXilinx, 15 | ImplFreePdk45, 16 | ImplLambdalib, 17 | ImplIce40 18 | } impl_e; 19 | endpackage : prim_pkg 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | FW ?= hello 2 | 3 | .PHONY: all 4 | all: zerosoc_hello.bit 5 | 6 | .PHONY: clean 7 | clean: 8 | rm -f *.asc *.bit zerosoc.vcd 9 | make -C sw/ clean 10 | 11 | zerosoc_%.asc: build/top_icebreaker/job0/apr/0/outputs/top_icebreaker.asc sw/%.mem 12 | icebram -v random.mem sw/$*.mem < $< > $@ 13 | 14 | zerosoc_%.bit: zerosoc_%.asc 15 | icepack $< $@ 16 | 17 | sw/%.mem: sw/%.c 18 | make -C sw/ $*.mem 19 | 20 | # Simulation 21 | 22 | sim/soc_tb.out: sim/zerosoc_tb.v zerosoc.v sw/hello.mem 23 | iverilog -g2005-sv -v -o $@ $< zerosoc_sim.v -------------------------------------------------------------------------------- /openroad/global_connect_core_top.tcl: -------------------------------------------------------------------------------- 1 | #################################### 2 | # global connections 3 | #################################### 4 | add_global_connection -net {vdd} -pin_pattern {VDD} -power 5 | add_global_connection -net {vdd} -pin_pattern {VPWR} 6 | add_global_connection -net {vdd} -pin_pattern {VPB} 7 | add_global_connection -net {vdd} -pin_pattern {_vdd} 8 | add_global_connection -net {vss} -pin_pattern {VSS} -ground 9 | add_global_connection -net {vss} -pin_pattern {VGND} 10 | add_global_connection -net {vss} -pin_pattern {VNB} 11 | add_global_connection -net {vss} -pin_pattern {_vss} 12 | -------------------------------------------------------------------------------- /openroad/global_connect_core.tcl: -------------------------------------------------------------------------------- 1 | #################################### 2 | # global connections 3 | #################################### 4 | add_global_connection -net {_vdd} -pin_pattern {VDD} -power 5 | add_global_connection -net {_vdd} -pin_pattern {VPWR} 6 | add_global_connection -net {_vdd} -pin_pattern {VPB} 7 | add_global_connection -net {_vdd} -pin_pattern {vdd} 8 | add_global_connection -net {_vss} -pin_pattern {VSS} -ground 9 | add_global_connection -net {_vss} -pin_pattern {VGND} 10 | add_global_connection -net {_vss} -pin_pattern {VNB} 11 | add_global_connection -net {_vss} -pin_pattern {gnd} 12 | -------------------------------------------------------------------------------- /openroad/global_connect_core_top_flat.tcl: -------------------------------------------------------------------------------- 1 | #################################### 2 | # global connections 3 | #################################### 4 | add_global_connection -net {vdd} -pin_pattern {VDD} -power 5 | add_global_connection -net {vdd} -pin_pattern {VPWR} 6 | add_global_connection -net {vdd} -pin_pattern {VPB} 7 | add_global_connection -net {vdd} -pin_pattern {vdd} 8 | add_global_connection -net {vss} -pin_pattern {VSS} -ground 9 | add_global_connection -net {vss} -pin_pattern {VGND} 10 | add_global_connection -net {vss} -pin_pattern {VNB} 11 | add_global_connection -net {vss} -pin_pattern {gnd} 12 | -------------------------------------------------------------------------------- /hw/prim/README.md: -------------------------------------------------------------------------------- 1 | # Prim Wrappers 2 | 3 | These prim wrappers were autogenerated by running the fusesoc "setup" step in 4 | the OpenTitan top-level directory (any random target works, but I used lint): 5 | 6 | `fusesoc --cores-root . run --setup --target lint lowrisc:systems:top_earlgrey` 7 | 8 | I then copied the generated wrappers into this directory using (starting from 9 | `hw/`): 10 | 11 | `mv opentitan/build/lowrisc_systems_top_earlgrey_0.1/src/lowrisc_prim_abstract*/* prim/` 12 | 13 | Note: OpenTitan primgen requires using a custom version of FuseSoC, which will 14 | be installed automatically if you set up a virtualenv from 15 | `opentitan/python-requirements.txt`. -------------------------------------------------------------------------------- /sw/entry.s: -------------------------------------------------------------------------------- 1 | # Exception handler - for now, just loops forever. 2 | .org 0x00 3 | _exception_handler: 4 | j _exception_handler 5 | 6 | # Main code entry point 7 | .org 0x80 8 | _entry: 9 | # TODO: should do more reset (set up exception-handling stuff, clear all regs) 10 | 11 | # Set up the global pointer. This requires that we disable linker relaxations 12 | # (or it will be relaxed to `mv gp, gp`). 13 | .option push 14 | .option norelax 15 | la gp, __global_pointer$ 16 | .option pop 17 | 18 | # set stack pointer 19 | la sp, _stack_end 20 | 21 | # call main function 22 | call main 23 | 24 | _hang: 25 | # hang if main returns 26 | j _hang 27 | -------------------------------------------------------------------------------- /sw/lib/zerosoc.h: -------------------------------------------------------------------------------- 1 | #ifndef PERIPHERALS_H 2 | 3 | #define PERIPHERALS_H 4 | 5 | #include "sw/device/lib/dif/dif_gpio.h" 6 | #include "sw/device/lib/dif/dif_uart.h" 7 | 8 | typedef struct zerosoc_t { 9 | dif_gpio_t gpio; 10 | dif_uart_t uart; 11 | } zerosoc_t; 12 | 13 | bool init_peripherals(zerosoc_t *soc); 14 | 15 | bool gpio_read(zerosoc_t *soc, int pin); 16 | void gpio_write(zerosoc_t *soc, int pin, bool state); 17 | 18 | void uart_init (zerosoc_t *soc); 19 | size_t uart_write(zerosoc_t *soc, const char *buf, size_t len); 20 | /* 21 | * Read bytes over UART until we hit a newline or read max length bytes 22 | */ 23 | size_t uart_read(zerosoc_t *soc, char *buf, size_t max_len); 24 | size_t uart_bytes_available(zerosoc_t *soc); 25 | 26 | void delay(unsigned long msec); 27 | uint64_t millis(); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /sim/zerosoc_tb.v: -------------------------------------------------------------------------------- 1 | module zerosoc_tb(); 2 | 3 | reg clk; 4 | reg rst; 5 | 6 | wire uart_tx, uart_tx_en; 7 | wire [31:0] gpio, gpio_en; 8 | 9 | zerosoc #( 10 | .RamInitFile("sw/hello.mem") 11 | ) uut ( 12 | .clk_i(clk), 13 | .rst_ni(rst), 14 | .uart_rx_i(1'b0), 15 | .uart_tx_o(uart_tx), 16 | .uart_tx_en_o(uart_tx_en), 17 | .gpio_i(32'b0), 18 | .gpio_o(gpio), 19 | .gpio_en_o(gpio_en) 20 | ); 21 | 22 | initial begin 23 | forever #1 clk = !clk; 24 | end 25 | 26 | initial begin 27 | clk = 1'b0; 28 | rst = 1'b1; 29 | #5; 30 | rst = 1'b0; 31 | #5; 32 | rst = 1'b1; 33 | #10000; 34 | $finish; 35 | end 36 | 37 | initial begin 38 | // Set variables to be dumped to vcd file here 39 | $dumpfile("zerosoc.vcd"); 40 | $dumpvars; 41 | end 42 | 43 | endmodule 44 | -------------------------------------------------------------------------------- /openroad/pdngen_core_only.tcl: -------------------------------------------------------------------------------- 1 | #################################### 2 | # voltage domains 3 | #################################### 4 | set_voltage_domain -name {CORE} -power {_vdd} -ground {_vss} 5 | #################################### 6 | # standard cell grid 7 | #################################### 8 | define_pdn_grid -name {grid} -voltage_domains {CORE} -pins met4 9 | add_pdn_stripe -grid {grid} -layer {met1} -width {0.48} -pitch {5.44} -offset {0} -followpins 10 | add_pdn_stripe -grid {grid} -layer {met4} -width {1.600} -pitch {27.140} -offset {13.570} 11 | # Set to large pitch as the chip grid needs to be able to get met5 straps in too 12 | add_pdn_stripe -grid {grid} -layer {met5} -width {1.600} -pitch {160.000} -offset {80.000} 13 | add_pdn_connect -grid {grid} -layers {met1 met4} 14 | add_pdn_connect -grid {grid} -layers {met4 met5} 15 | -------------------------------------------------------------------------------- /hw/prim/prim_clock_inv.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | 8 | // This is to prevent AscentLint warnings in the generated 9 | // abstract prim wrapper. These warnings occur due to the .* 10 | // use. TODO: we may want to move these inline waivers 11 | // into a separate, generated waiver file for consistency. 12 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 13 | module prim_clock_inv 14 | 15 | #( 16 | 17 | parameter bit HasScanMode = 1'b1 18 | 19 | ) ( 20 | input clk_i, 21 | input scanmode_i, 22 | output logic clk_no // Inverted 23 | ); 24 | 25 | if (1) begin : gen_generic 26 | prim_generic_clock_inv #( 27 | .HasScanMode(HasScanMode) 28 | ) u_impl_generic ( 29 | .* 30 | ); 31 | 32 | end 33 | 34 | endmodule 35 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 36 | -------------------------------------------------------------------------------- /hw/prim/lambdalib/prim_lambdalib_ram_1p.v: -------------------------------------------------------------------------------- 1 | module prim_lambdalib_ram_1p 2 | import prim_ram_1p_pkg::*; 3 | #( 4 | 5 | parameter int Width = 32, // bit 6 | parameter int Depth = 512, 7 | parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask 8 | parameter MemInitFile = "", // VMEM file to initialize the memory with 9 | 10 | localparam int Aw = $clog2(Depth) // derived parameter 11 | 12 | ) ( 13 | input logic clk_i, 14 | 15 | input logic req_i, 16 | input logic write_i, 17 | input logic [Aw-1:0] addr_i, 18 | input logic [Width-1:0] wdata_i, 19 | input logic [Width-1:0] wmask_i, 20 | output logic [Width-1:0] rdata_o, // Read data. Data is returned one cycle after req_i is high. 21 | input ram_1p_cfg_t cfg_i 22 | ); 23 | 24 | la_spram #(.DW(Width), .AW(Aw)) mem( 25 | .clk(clk_i), 26 | .ce(req_i), 27 | .we(write_i), 28 | .wmask(wmask_i), 29 | .addr(addr_i), 30 | .din(wdata_i), 31 | .dout(rdata_o) 32 | ); 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /hw/prim/prim_clock_buf.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | `ifndef PRIM_DEFAULT_IMPL 8 | `define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric 9 | `endif 10 | 11 | // This is to prevent AscentLint warnings in the generated 12 | // abstract prim wrapper. These warnings occur due to the .* 13 | // use. TODO: we may want to move these inline waivers 14 | // into a separate, generated waiver file for consistency. 15 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 16 | module prim_clock_buf 17 | 18 | #( 19 | 20 | ) ( 21 | input clk_i, 22 | output logic clk_o 23 | ); 24 | parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL; 25 | 26 | if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx 27 | prim_xilinx_clock_buf u_impl_xilinx ( 28 | .* 29 | ); 30 | end else begin : gen_generic 31 | prim_generic_clock_buf u_impl_generic ( 32 | .* 33 | ); 34 | end 35 | 36 | endmodule 37 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 38 | -------------------------------------------------------------------------------- /openroad/pdngen_top.tcl: -------------------------------------------------------------------------------- 1 | #################################### 2 | # voltage domains 3 | #################################### 4 | set_voltage_domain -name {CORE} -power {vdd} -ground {vss} 5 | #################################### 6 | # standard cell grid 7 | #################################### 8 | define_pdn_grid -name {grid} -voltage_domains {CORE} 9 | add_pdn_stripe -grid {grid} -layer {met1} -width {0.48} -pitch {5.44} -offset {0} -followpins 10 | add_pdn_ring -connect_to_pads -layers {met4 met5} -widths {2.0 2.0} -spacings {2.0 2.0} -core_offsets {1.0 1.0 1.0 1.0} 11 | add_pdn_ring -connect_to_pads -layers {met2 met3} -widths {2.0 2.0} -spacings {2.0 2.0} -core_offsets {1.0 1.0 1.0 1.0} 12 | add_pdn_stripe -grid {grid} -layer {met4} -width {1.600} -pitch {27.140} -offset {13.570} -extend_to_core_ring 13 | add_pdn_stripe -grid {grid} -layer {met5} -width {1.600} -pitch {27.200} -offset {13.600} -extend_to_core_ring 14 | add_pdn_connect -grid {grid} -layers {met1 met4} 15 | add_pdn_connect -grid {grid} -layers {met2 met3} 16 | add_pdn_connect -grid {grid} -layers {met3 met4} 17 | add_pdn_connect -grid {grid} -layers {met4 met5} 18 | -------------------------------------------------------------------------------- /hw/prim/prim_flop_2sync.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | 8 | // This is to prevent AscentLint warnings in the generated 9 | // abstract prim wrapper. These warnings occur due to the .* 10 | // use. TODO: we may want to move these inline waivers 11 | // into a separate, generated waiver file for consistency. 12 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 13 | module prim_flop_2sync 14 | 15 | #( 16 | 17 | parameter int Width = 16, 18 | parameter logic [Width-1:0] ResetValue = '0 19 | 20 | ) ( 21 | input clk_i, 22 | input rst_ni, 23 | input [Width-1:0] d_i, 24 | output logic [Width-1:0] q_o 25 | ); 26 | 27 | if (1) begin : gen_generic 28 | prim_generic_flop_2sync #( 29 | .ResetValue(ResetValue), 30 | .Width(Width) 31 | ) u_impl_generic ( 32 | .* 33 | ); 34 | 35 | end 36 | 37 | endmodule 38 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 39 | -------------------------------------------------------------------------------- /hw/prim/prim_buf.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | `ifndef PRIM_DEFAULT_IMPL 8 | `define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric 9 | `endif 10 | 11 | // This is to prevent AscentLint warnings in the generated 12 | // abstract prim wrapper. These warnings occur due to the .* 13 | // use. TODO: we may want to move these inline waivers 14 | // into a separate, generated waiver file for consistency. 15 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 16 | module prim_buf 17 | 18 | #( 19 | 20 | parameter int Width = 1 21 | 22 | ) ( 23 | input [Width-1:0] in_i, 24 | output logic [Width-1:0] out_o 25 | ); 26 | parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL; 27 | 28 | if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx 29 | prim_xilinx_buf #( 30 | .Width(Width) 31 | ) u_impl_xilinx ( 32 | .* 33 | ); 34 | end else begin : gen_generic 35 | prim_generic_buf #( 36 | .Width(Width) 37 | ) u_impl_generic ( 38 | .* 39 | ); 40 | end 41 | 42 | endmodule 43 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 44 | -------------------------------------------------------------------------------- /hw/prim/prim_xor2.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | `ifndef PRIM_DEFAULT_IMPL 8 | `define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric 9 | `endif 10 | 11 | // This is to prevent AscentLint warnings in the generated 12 | // abstract prim wrapper. These warnings occur due to the .* 13 | // use. TODO: we may want to move these inline waivers 14 | // into a separate, generated waiver file for consistency. 15 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 16 | module prim_xor2 17 | 18 | #( 19 | 20 | parameter int Width = 1 21 | 22 | ) ( 23 | input [Width-1:0] in0_i, 24 | input [Width-1:0] in1_i, 25 | output logic [Width-1:0] out_o 26 | ); 27 | parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL; 28 | 29 | if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx 30 | prim_xilinx_xor2 #( 31 | .Width(Width) 32 | ) u_impl_xilinx ( 33 | .* 34 | ); 35 | end else begin : gen_generic 36 | prim_generic_xor2 #( 37 | .Width(Width) 38 | ) u_impl_generic ( 39 | .* 40 | ); 41 | end 42 | 43 | endmodule 44 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 45 | -------------------------------------------------------------------------------- /hw/prim/prim_pad_attr.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | `ifndef PRIM_DEFAULT_IMPL 8 | `define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric 9 | `endif 10 | 11 | // This is to prevent AscentLint warnings in the generated 12 | // abstract prim wrapper. These warnings occur due to the .* 13 | // use. TODO: we may want to move these inline waivers 14 | // into a separate, generated waiver file for consistency. 15 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 16 | module prim_pad_attr 17 | import prim_pad_wrapper_pkg::*; 18 | #( 19 | 20 | parameter pad_type_e PadType = BidirStd // currently ignored in the generic model 21 | 22 | ) ( 23 | output pad_attr_t attr_warl_o 24 | ); 25 | parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL; 26 | 27 | if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx 28 | prim_xilinx_pad_attr #( 29 | .PadType(PadType) 30 | ) u_impl_xilinx ( 31 | .* 32 | ); 33 | end else begin : gen_generic 34 | prim_generic_pad_attr #( 35 | .PadType(PadType) 36 | ) u_impl_generic ( 37 | .* 38 | ); 39 | end 40 | 41 | endmodule 42 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 43 | -------------------------------------------------------------------------------- /hw/prim/prim_rom.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | 8 | // This is to prevent AscentLint warnings in the generated 9 | // abstract prim wrapper. These warnings occur due to the .* 10 | // use. TODO: we may want to move these inline waivers 11 | // into a separate, generated waiver file for consistency. 12 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 13 | module prim_rom 14 | import prim_rom_pkg::*; 15 | #( 16 | 17 | parameter int Width = 32, 18 | parameter int Depth = 2048, // 8kB default 19 | parameter MemInitFile = "", // VMEM file to initialize the memory with 20 | 21 | localparam int Aw = $clog2(Depth) 22 | 23 | ) ( 24 | input logic clk_i, 25 | input logic req_i, 26 | input logic [Aw-1:0] addr_i, 27 | output logic [Width-1:0] rdata_o, 28 | input rom_cfg_t cfg_i 29 | ); 30 | 31 | if (1) begin : gen_generic 32 | prim_generic_rom #( 33 | .Width(Width), 34 | .Depth(Depth), 35 | .MemInitFile(MemInitFile) 36 | ) u_impl_generic ( 37 | .* 38 | ); 39 | 40 | end 41 | 42 | endmodule 43 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 44 | -------------------------------------------------------------------------------- /hw/top_icebreaker.v: -------------------------------------------------------------------------------- 1 | module top_icebreaker ( 2 | input CLK, 3 | input BTN_N, 4 | 5 | input RX, 6 | output TX, 7 | 8 | input BTN1, 9 | input BTN2, 10 | input BTN3, 11 | 12 | output LED1, 13 | output LED2, 14 | output LED3, 15 | output LED4, 16 | output LED5 17 | ); 18 | 19 | wire clk_6mhz; 20 | 21 | SB_HFOSC #( 22 | .CLKHF_DIV("0b11") // 6mhz 23 | ) clock_gen ( 24 | .CLKHFPU(1'b1), 25 | .CLKHFEN(1'b1), 26 | .CLKHF(clk_6mhz) 27 | ); 28 | 29 | wire [2:0] gpio_in; 30 | assign gpio_in[0] = BTN1; 31 | assign gpio_in[1] = BTN2; 32 | assign gpio_in[2] = BTN3; 33 | 34 | wire [31:0] gpio_out; 35 | assign LED1 = gpio_out[0]; 36 | assign LED2 = gpio_out[1]; 37 | assign LED3 = gpio_out[2]; 38 | assign LED4 = gpio_out[3]; 39 | assign LED5 = gpio_out[4]; 40 | 41 | `define MAKE_MEM_PATH(filename) `"`MEM_ROOT/filename`" 42 | 43 | zerosoc #( 44 | .RamInitFile(`MAKE_MEM_PATH(random.mem)), 45 | .RamDepth(2048), 46 | .ASIC(0) 47 | ) soc( 48 | .clk_i(clk_6mhz), 49 | .rst_ni(BTN_N), 50 | 51 | .uart_rx_i(RX), 52 | .uart_tx_o(TX), 53 | .uart_tx_en_o(), 54 | 55 | .gpio_i({29'b0, gpio_in}), 56 | .gpio_o(gpio_out), 57 | .gpio_en_o() 58 | ); 59 | 60 | endmodule 61 | -------------------------------------------------------------------------------- /hw/prim/prim_clock_mux2.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | `ifndef PRIM_DEFAULT_IMPL 8 | `define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric 9 | `endif 10 | 11 | // This is to prevent AscentLint warnings in the generated 12 | // abstract prim wrapper. These warnings occur due to the .* 13 | // use. TODO: we may want to move these inline waivers 14 | // into a separate, generated waiver file for consistency. 15 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 16 | module prim_clock_mux2 17 | 18 | #( 19 | 20 | parameter bit NoFpgaBufG = 1'b0 // this parameter serves no function in the generic model 21 | 22 | ) ( 23 | input clk0_i, 24 | input clk1_i, 25 | input sel_i, 26 | output logic clk_o 27 | ); 28 | parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL; 29 | 30 | if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx 31 | prim_xilinx_clock_mux2 #( 32 | .NoFpgaBufG(NoFpgaBufG) 33 | ) u_impl_xilinx ( 34 | .* 35 | ); 36 | end else begin : gen_generic 37 | prim_generic_clock_mux2 #( 38 | .NoFpgaBufG(NoFpgaBufG) 39 | ) u_impl_generic ( 40 | .* 41 | ); 42 | end 43 | 44 | endmodule 45 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 46 | -------------------------------------------------------------------------------- /hw/prim/prim_usb_diff_rx.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | 8 | // This is to prevent AscentLint warnings in the generated 9 | // abstract prim wrapper. These warnings occur due to the .* 10 | // use. TODO: we may want to move these inline waivers 11 | // into a separate, generated waiver file for consistency. 12 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 13 | module prim_usb_diff_rx 14 | 15 | #( 16 | 17 | parameter int CalibW = 32 18 | 19 | ) ( 20 | input wire input_pi, // differential input 21 | input wire input_ni, // differential input 22 | input input_en_i, // input buffer enable 23 | input core_pok_i, // core power indication at VCC level 24 | input pullup_p_en_i, // pullup enable for P 25 | input pullup_n_en_i, // pullup enable for N 26 | input [CalibW-1:0] calibration_i, // calibration input 27 | output logic input_o // output of differential input buffer 28 | ); 29 | 30 | if (1) begin : gen_generic 31 | prim_generic_usb_diff_rx #( 32 | .CalibW(CalibW) 33 | ) u_impl_generic ( 34 | .* 35 | ); 36 | 37 | end 38 | 39 | endmodule 40 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 41 | -------------------------------------------------------------------------------- /zerosoc_core.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shlex 3 | from siliconcompiler import Library 4 | from siliconcompiler.package import path as sc_path 5 | import opentitan 6 | from lambdalib import ramlib 7 | 8 | 9 | def setup(): 10 | lib = Library("zerosoc_core", package='zerosoc', auto_enable=True) 11 | lib.register_source( 12 | name='zerosoc', 13 | path=os.path.abspath(os.path.dirname(__file__))) 14 | 15 | lib.add('option', 'idir', 'hw') 16 | lib.add('option', 'ydir', 'hw/prim') 17 | # lib.input('hw/asic_top.v') 18 | lib.input('hw/xbar_pkg.sv') 19 | lib.input('hw/prim/prim_pkg.sv') 20 | 21 | lib.input('hw/uart_core.sv') 22 | 23 | lib.input('hw/zerosoc.sv') 24 | lib.input('hw/xbar.sv') 25 | lib.input('hw/tl_dbg.sv') 26 | 27 | lib.input('hw/asic_core.v') 28 | 29 | # TODO: break into separate lib 30 | lib.input('hw/prim/lambdalib/prim_lambdalib_ram_1p.v') 31 | lib.input('hw/prim/lambdalib/prim_lambdalib_clock_gating.v') 32 | 33 | # hack to work around fact that $readmemh now runs in context of build 34 | # directory and can't load .mem files using relative paths 35 | lib.add('option', 'define', f'MEM_ROOT={shlex.quote(sc_path(lib, "zerosoc"))}') 36 | lib.add('option', 'define', 'PRIM_DEFAULT_IMPL=prim_pkg::ImplLambdalib') 37 | lib.add('option', 'define', 'RAM_DEPTH=512') 38 | 39 | lib.use(opentitan) 40 | lib.use(ramlib) 41 | 42 | return lib 43 | -------------------------------------------------------------------------------- /hw/prim/prim_flop.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | `ifndef PRIM_DEFAULT_IMPL 8 | `define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric 9 | `endif 10 | 11 | // This is to prevent AscentLint warnings in the generated 12 | // abstract prim wrapper. These warnings occur due to the .* 13 | // use. TODO: we may want to move these inline waivers 14 | // into a separate, generated waiver file for consistency. 15 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 16 | module prim_flop 17 | 18 | #( 19 | 20 | parameter int Width = 1, 21 | parameter logic [Width-1:0] ResetValue = 0 22 | 23 | ) ( 24 | input clk_i, 25 | input rst_ni, 26 | input [Width-1:0] d_i, 27 | output logic [Width-1:0] q_o 28 | ); 29 | parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL; 30 | 31 | if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx 32 | prim_xilinx_flop #( 33 | .ResetValue(ResetValue), 34 | .Width(Width) 35 | ) u_impl_xilinx ( 36 | .* 37 | ); 38 | end else begin : gen_generic 39 | prim_generic_flop #( 40 | .ResetValue(ResetValue), 41 | .Width(Width) 42 | ) u_impl_generic ( 43 | .* 44 | ); 45 | end 46 | 47 | endmodule 48 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 49 | -------------------------------------------------------------------------------- /hw/prim/prim_flop_en.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | `ifndef PRIM_DEFAULT_IMPL 8 | `define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric 9 | `endif 10 | 11 | // This is to prevent AscentLint warnings in the generated 12 | // abstract prim wrapper. These warnings occur due to the .* 13 | // use. TODO: we may want to move these inline waivers 14 | // into a separate, generated waiver file for consistency. 15 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 16 | module prim_flop_en 17 | 18 | #( 19 | 20 | parameter int Width = 1, 21 | parameter logic [Width-1:0] ResetValue = 0 22 | 23 | ) ( 24 | input clk_i, 25 | input rst_ni, 26 | input en_i, 27 | input [Width-1:0] d_i, 28 | output logic [Width-1:0] q_o 29 | ); 30 | parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL; 31 | 32 | if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx 33 | prim_xilinx_flop_en #( 34 | .ResetValue(ResetValue), 35 | .Width(Width) 36 | ) u_impl_xilinx ( 37 | .* 38 | ); 39 | end else begin : gen_generic 40 | prim_generic_flop_en #( 41 | .ResetValue(ResetValue), 42 | .Width(Width) 43 | ) u_impl_generic ( 44 | .* 45 | ); 46 | end 47 | 48 | endmodule 49 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 50 | -------------------------------------------------------------------------------- /docs/fpga.md: -------------------------------------------------------------------------------- 1 | # ZeroSoC FPGA 2 | 3 | ZeroSoC includes an option to build a bitstream targeting the Icebreaker dev 4 | board. It also includes a demo program, `sw/hello.c`, that will blink the 5 | Icebreaker LEDs and output messages over UART. The speed of the blinking can be 6 | adjusted using the onboard buttons or by entering the characters `f`, `s`, or 7 | `r` via a UART console. 8 | 9 | ## Building firmware 10 | 11 | Building the firmware requires installing the [RISC-V 12 | toolchain](https://github.com/riscv/riscv-gnu-toolchain). We've tested the 13 | firmware build with a toolchain configured using `--with-arch=rv32i 14 | --with-abi=ilp32`, built for Newlib. In addition, a prebuilt multilib toolchain can be 15 | downloaded from Embecosm: 16 | ``` 17 | $ wget https://buildbot.embecosm.com/job/riscv32-gcc-centos7/67/artifact/riscv32-embecosm-gcc-centos7-20210530.tar.gz 18 | $ tar xvf riscv32-embecosm-gcc-centos7-20210530.tar.gz --strip-components=1 -C ~/.local/ 19 | ``` 20 | 21 | Generating a `.mem` file requires the Python utility 22 | [bin2coe](https://github.com/anishathalye/bin2coe). 23 | 24 | Once these prerequisites are installed, cd into `sw/` and run `make 25 | gen/gpio_regs.h`, followed by `make`. 26 | 27 | ## Building bitstream 28 | 29 | Once the firmware is built, build an FPGA bistream by running: 30 | ``` 31 | ./build.py --fpga 32 | ``` 33 | 34 | Next, to embed the firmware in the FPGA bitstream, run: 35 | ``` 36 | make zerosoc_hello.bit 37 | ``` 38 | 39 | Finally, to flash this bitstream on a connected Icebreaker dev board, run: 40 | ``` 41 | iceprog zerosoc_hello.bit 42 | ``` 43 | -------------------------------------------------------------------------------- /hw/prim/prim_clock_gating.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | `ifndef PRIM_DEFAULT_IMPL 8 | `define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric 9 | `endif 10 | 11 | // This is to prevent AscentLint warnings in the generated 12 | // abstract prim wrapper. These warnings occur due to the .* 13 | // use. TODO: we may want to move these inline waivers 14 | // into a separate, generated waiver file for consistency. 15 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 16 | module prim_clock_gating 17 | 18 | #( 19 | 20 | parameter bit NoFpgaGate = 1'b0 // this parameter has no function in generic 21 | 22 | ) ( 23 | input clk_i, 24 | input en_i, 25 | input test_en_i, 26 | output logic clk_o 27 | ); 28 | parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL; 29 | 30 | if (Impl == prim_pkg::ImplLambdalib) begin : gen_lambdalib 31 | prim_lambdalib_clock_gating #( 32 | .NoFpgaGate(NoFpgaGate) 33 | ) u_impl_lambdalib ( 34 | .* 35 | ); 36 | end else if (Impl == prim_pkg::ImplIce40) begin : gen_ice40 37 | prim_ice40_clock_gating #( 38 | .NoFpgaGate(NoFpgaGate) 39 | ) u_impl_ice40 ( 40 | .* 41 | ); 42 | end else begin : gen_generic 43 | prim_generic_clock_gating #( 44 | .NoFpgaGate(NoFpgaGate) 45 | ) u_impl_generic ( 46 | .* 47 | ); 48 | end 49 | 50 | endmodule 51 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 52 | -------------------------------------------------------------------------------- /hw/iomap.vh: -------------------------------------------------------------------------------- 1 | //################################################## 2 | // PIN ORDER (PER SIDE) 3 | //################################################## 4 | 5 | localparam [7:0] PIN_IO0 = 8'h00; 6 | localparam [7:0] PIN_IO1 = 8'h01; 7 | localparam [7:0] PIN_IO2 = 8'h02; 8 | localparam [7:0] PIN_IO3 = 8'h03; 9 | localparam [7:0] PIN_IO4 = 8'h04; 10 | localparam [7:0] PIN_IO5 = 8'h05; 11 | localparam [7:0] PIN_IO6 = 8'h06; 12 | localparam [7:0] PIN_IO7 = 8'h07; 13 | localparam [7:0] PIN_IO8 = 8'h08; 14 | 15 | localparam [7:0] PIN_NONE = 8'hFF; 16 | 17 | //################################################## 18 | // CELLMAP = {PROP[7:0],SECTION[7:0],CELL[7:0],COMP[7:0],PIN[7:0]} 19 | //################################################## 20 | 21 | `include "la_padring.vh" 22 | 23 | localparam CELLMAP = { // GPIO SECTION 24 | {8'h0, 8'h0, LA_VSS, 8'h0, PIN_NONE}, 25 | {8'h0, 8'h0, LA_VDD, 8'h0, PIN_NONE}, 26 | {8'h0, 8'h0, LA_VDDIO, 8'h0, PIN_NONE}, 27 | {8'h0, 8'h0, LA_VSSIO, 8'h0, PIN_NONE}, 28 | {8'h0, 8'h0, LA_BIDIR, 8'h0, PIN_IO0}, 29 | {8'h0, 8'h0, LA_BIDIR, 8'h0, PIN_IO1}, 30 | {8'h0, 8'h0, LA_BIDIR, 8'h0, PIN_IO2}, 31 | {8'h0, 8'h0, LA_BIDIR, 8'h0, PIN_IO3}, 32 | {8'h0, 8'h0, LA_BIDIR, 8'h0, PIN_IO4}, 33 | {8'h0, 8'h0, LA_BIDIR, 8'h0, PIN_IO5}, 34 | {8'h0, 8'h0, LA_BIDIR, 8'h0, PIN_IO6}, 35 | {8'h0, 8'h0, LA_BIDIR, 8'h0, PIN_IO7}, 36 | {8'h0, 8'h0, LA_BIDIR, 8'h0, PIN_IO8}}; 37 | -------------------------------------------------------------------------------- /sw/Makefile: -------------------------------------------------------------------------------- 1 | ROM_DEPTH := 2048 2 | 3 | PREFIX := riscv32-unknown-elf- 4 | 5 | PERIPHERALS := gpio uart 6 | 7 | REGS_HDRS := $(patsubst %,gen/%_regs.h, $(PERIPHERALS)) 8 | 9 | DIF_SRCS := $(patsubst %,../opentitan/sw/device/lib/dif/dif_%.c, $(PERIPHERALS)) 10 | DIF_HEADERS := $(DIF_SRCS:.c=.h) 11 | DIF_OBJS := $(DIF_SRCS:.c=.o) 12 | 13 | CC := $(PREFIX)gcc 14 | AS := $(PREFIX)as 15 | LD := $(PREFIX)ld 16 | OBJCOPY := $(PREFIX)objcopy 17 | OBJDUMP := $(PREFIX)objdump 18 | 19 | CFLAGS := -O2 -march=rv32i -mabi=ilp32 -fdata-sections -ffunction-sections -ffreestanding -I../opentitan/ -Igen/ 20 | ASFLAGS := -march=rv32i -mabi=ilp32 21 | OBJDUMPFLAGS := --disassemble-all --source --section-headers --demangle 22 | LDFLAGS := -Wl,-melf32lriscv -nostdlib -march=rv32i -mabi=ilp32 23 | BIN2COEFLAGS := --width 32 --depth $(ROM_DEPTH) --fill 0 24 | 25 | all: hello.mem 26 | 27 | lib/zerosoc.o: lib/zerosoc.h 28 | 29 | gen/%_regs.h: 30 | @mkdir -p gen/ 31 | ../opentitan/util/regtool.py -D -o $@ ../opentitan/hw/ip/$*/data/$*.hjson 32 | 33 | # Pattern variables don't work here for some reason 34 | ../opentitan/sw/device/lib/dif/dif_gpio.o: gen/gpio_regs.h 35 | ../opentitan/sw/device/lib/dif/dif_uart.o: gen/uart_regs.h 36 | 37 | %.bin: %.elf 38 | $(OBJCOPY) $< -O binary $@ 39 | 40 | %.o: %.c 41 | $(CC) $(CFLAGS) -c $< -o $@ 42 | 43 | %.o: %.s 44 | $(AS) $(ASFLAGS) -c $< -o $@ 45 | 46 | %.lst: %.elf 47 | $(OBJDUMP) $(OBJDUMPFLAGS) $< > $@ 48 | 49 | .SECONDARY: 50 | %.elf: ram.ld %.o entry.o lib/zerosoc.o $(DIF_OBJS) 51 | $(CC) $(LDFLAGS) -T $^ -o $@ 52 | 53 | %.mem: %.bin 54 | bin2coe $(BIN2COEFLAGS) --mem -i $< -o $@ 55 | 56 | .PHONY: clean 57 | clean: 58 | rm -f *.o *.elf *.bin *.mem lib/*.o gen/*.h $(DIF_OBJS) 59 | -------------------------------------------------------------------------------- /fpga/icebreaker.pcf: -------------------------------------------------------------------------------- 1 | ## Source: https://github.com/icebreaker-fpga/icebreaker-examples/blob/master/icebreaker.pcf 2 | 3 | # 12 MHz clock 4 | set_io -nowarn CLK 35 5 | 6 | # RS232 7 | set_io -nowarn RX 6 8 | set_io -nowarn TX 9 9 | 10 | # LEDs and Button 11 | set_io -nowarn BTN_N 10 12 | set_io -nowarn LEDR_N 11 13 | set_io -nowarn LEDG_N 37 14 | 15 | # RGB LED Driver 16 | set_io -nowarn LED_RED_N 39 17 | set_io -nowarn LED_GRN_N 40 18 | set_io -nowarn LED_BLU_N 41 19 | 20 | # SPI Flash 21 | set_io -nowarn FLASH_SCK 15 22 | set_io -nowarn FLASH_SSB 16 23 | set_io -nowarn FLASH_IO0 14 24 | set_io -nowarn FLASH_IO1 17 25 | set_io -nowarn FLASH_IO2 12 26 | set_io -nowarn FLASH_IO3 13 27 | 28 | # PMOD 1A 29 | set_io -nowarn P1A1 4 30 | set_io -nowarn P1A2 2 31 | set_io -nowarn P1A3 47 32 | set_io -nowarn P1A4 45 33 | set_io -nowarn P1A7 3 34 | set_io -nowarn P1A8 48 35 | set_io -nowarn P1A9 46 36 | set_io -nowarn P1A10 44 37 | 38 | # PMOD 1B 39 | set_io -nowarn P1B1 43 40 | set_io -nowarn P1B2 38 41 | set_io -nowarn P1B3 34 42 | set_io -nowarn P1B4 31 43 | set_io -nowarn P1B7 42 44 | set_io -nowarn P1B8 36 45 | set_io -nowarn P1B9 32 46 | set_io -nowarn P1B10 28 47 | 48 | # PMOD 2 49 | set_io -nowarn P2_1 27 50 | set_io -nowarn P2_2 25 51 | set_io -nowarn P2_3 21 52 | set_io -nowarn P2_4 19 53 | set_io -nowarn P2_7 26 54 | set_io -nowarn P2_8 23 55 | set_io -nowarn P2_9 20 56 | set_io -nowarn P2_10 18 57 | 58 | # LEDs and Buttons (PMOD 2) 59 | set_io -nowarn LED1 26 60 | set_io -nowarn LED2 27 61 | set_io -nowarn LED3 25 62 | set_io -nowarn LED4 23 63 | set_io -nowarn LED5 21 64 | set_io -nowarn BTN1 20 65 | set_io -nowarn BTN2 19 66 | set_io -nowarn BTN3 18 -------------------------------------------------------------------------------- /hw/prim/prim_ram_2p.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | 8 | // This is to prevent AscentLint warnings in the generated 9 | // abstract prim wrapper. These warnings occur due to the .* 10 | // use. TODO: we may want to move these inline waivers 11 | // into a separate, generated waiver file for consistency. 12 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 13 | module prim_ram_2p 14 | import prim_ram_2p_pkg::*; 15 | #( 16 | 17 | parameter int Width = 32, // bit 18 | parameter int Depth = 128, 19 | parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask 20 | parameter MemInitFile = "", // VMEM file to initialize the memory with 21 | 22 | localparam int Aw = $clog2(Depth) // derived parameter 23 | 24 | ) ( 25 | input clk_a_i, 26 | input clk_b_i, 27 | 28 | input a_req_i, 29 | input a_write_i, 30 | input [Aw-1:0] a_addr_i, 31 | input [Width-1:0] a_wdata_i, 32 | input logic [Width-1:0] a_wmask_i, 33 | output logic [Width-1:0] a_rdata_o, 34 | 35 | 36 | input b_req_i, 37 | input b_write_i, 38 | input [Aw-1:0] b_addr_i, 39 | input [Width-1:0] b_wdata_i, 40 | input logic [Width-1:0] b_wmask_i, 41 | output logic [Width-1:0] b_rdata_o, 42 | 43 | input ram_2p_cfg_t cfg_i 44 | ); 45 | 46 | if (1) begin : gen_generic 47 | prim_generic_ram_2p #( 48 | .MemInitFile(MemInitFile), 49 | .DataBitsPerMask(DataBitsPerMask), 50 | .Depth(Depth), 51 | .Width(Width) 52 | ) u_impl_generic ( 53 | .* 54 | ); 55 | 56 | end 57 | 58 | endmodule 59 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 60 | -------------------------------------------------------------------------------- /sw/hello.c: -------------------------------------------------------------------------------- 1 | #include "lib/zerosoc.h" 2 | 3 | const int MIN_DELAY = 100; 4 | const int DEFAULT_DELAY = 800; 5 | const int MAX_DELAY = 1500; 6 | const int DELAY_INC = 100; 7 | 8 | int main() { 9 | zerosoc_t soc; 10 | init_peripherals(&soc); 11 | 12 | uart_write(&soc, "Hello world!\r\n", 14); 13 | 14 | bool btn1, btn2, btn3; 15 | bool prev_btn1 = false; 16 | bool prev_btn2 = false; 17 | bool prev_btn3 = false; 18 | 19 | int led = 0; 20 | int time = DEFAULT_DELAY; 21 | uint64_t last_changed = millis(); 22 | 23 | while (true) { 24 | // Light up next LED after `time` milliseconds elapse 25 | if (millis() - last_changed > time) { 26 | gpio_write(&soc, led, false); 27 | led++; 28 | if (led >= 5) led = 0; 29 | gpio_write(&soc, led, true); 30 | last_changed = millis(); 31 | } 32 | 33 | // Read UART 34 | // expect "f", "s", or "r" 35 | char cmd = '\0'; 36 | if (uart_bytes_available(&soc) > 0) { 37 | uart_read(&soc, &cmd, 1); 38 | } 39 | 40 | // Read buttons 41 | btn1 = gpio_read(&soc, 0); 42 | bool btn1_up = btn1 && !prev_btn1; 43 | prev_btn1 = btn1; 44 | 45 | btn2 = gpio_read(&soc, 1); 46 | bool btn2_up = btn2 && !prev_btn2; 47 | prev_btn2 = btn2; 48 | 49 | btn3 = gpio_read(&soc, 2); 50 | bool btn3_up = btn3 && !prev_btn3; 51 | prev_btn3 = btn3; 52 | 53 | // Adjust `time` accordingly based on input 54 | if (cmd == 's' || btn1_up) { 55 | time += DELAY_INC; 56 | if (time > MAX_DELAY) time = MAX_DELAY; 57 | uart_write(&soc, "Slower...\r\n", 11); 58 | } 59 | 60 | if (cmd == 'r' || btn2_up) { 61 | time = DEFAULT_DELAY; 62 | uart_write(&soc, "Reset...\r\n", 10); 63 | } 64 | 65 | if (cmd == 'f' || btn3_up) { 66 | time -= DELAY_INC; 67 | if (time < MIN_DELAY) time = MIN_DELAY; 68 | uart_write(&soc, "Faster...\r\n", 11); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /hw/prim/prim_pad_wrapper.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | `ifndef PRIM_DEFAULT_IMPL 8 | `define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric 9 | `endif 10 | 11 | // This is to prevent AscentLint warnings in the generated 12 | // abstract prim wrapper. These warnings occur due to the .* 13 | // use. TODO: we may want to move these inline waivers 14 | // into a separate, generated waiver file for consistency. 15 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 16 | module prim_pad_wrapper 17 | import prim_pad_wrapper_pkg::*; 18 | #( 19 | 20 | // These parameters are ignored in this model. 21 | parameter pad_type_e PadType = BidirStd, 22 | parameter scan_role_e ScanRole = NoScan 23 | 24 | ) ( 25 | // This is only used for scanmode (not used in generic models) 26 | input clk_scan_i, 27 | input scanmode_i, 28 | // Power sequencing signals (not used in generic models) 29 | input pad_pok_t pok_i, 30 | // Main Pad signals 31 | inout wire inout_io, // bidirectional pad 32 | output logic in_o, // input data 33 | output logic in_raw_o, // uninverted output data 34 | input ie_i, // input enable 35 | input out_i, // output data 36 | input oe_i, // output enable 37 | input pad_attr_t attr_i // additional pad attributes 38 | ); 39 | parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL; 40 | 41 | if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx 42 | prim_xilinx_pad_wrapper #( 43 | .PadType(PadType), 44 | .ScanRole(ScanRole) 45 | ) u_impl_xilinx ( 46 | .* 47 | ); 48 | end else begin : gen_generic 49 | prim_generic_pad_wrapper #( 50 | .PadType(PadType), 51 | .ScanRole(ScanRole) 52 | ) u_impl_generic ( 53 | .* 54 | ); 55 | end 56 | 57 | endmodule 58 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 59 | -------------------------------------------------------------------------------- /hw/tl_dbg.sv: -------------------------------------------------------------------------------- 1 | module tl_dbg( 2 | input tlul_pkg::tl_h2d_t tl_h2d, 3 | input tlul_pkg::tl_d2h_t tl_d2h 4 | ); 5 | 6 | import tlul_pkg::*; 7 | 8 | logic tl_h2d_a_valid; 9 | tl_a_op_e tl_h2d_a_opcode; 10 | logic [2:0] tl_h2d_a_param; 11 | logic [top_pkg::TL_SZW-1:0] tl_h2d_a_size; 12 | logic [top_pkg::TL_AIW-1:0] tl_h2d_a_source; 13 | logic [top_pkg::TL_AW-1:0] tl_h2d_a_address; 14 | logic [top_pkg::TL_DBW-1:0] tl_h2d_a_mask; 15 | logic [top_pkg::TL_DW-1:0] tl_h2d_a_data; 16 | tl_a_user_t tl_h2d_a_user; 17 | logic tl_h2d_d_ready; 18 | 19 | logic tl_d2h_d_valid; 20 | tl_d_op_e tl_d2h_d_opcode; 21 | logic [2:0] tl_d2h_d_param; 22 | logic [top_pkg::TL_SZW-1:0] tl_d2h_d_size; // Bouncing back a_size 23 | logic [top_pkg::TL_AIW-1:0] tl_d2h_d_source; 24 | logic [top_pkg::TL_DIW-1:0] tl_d2h_d_sink; 25 | logic [top_pkg::TL_DW-1:0] tl_d2h_d_data; 26 | logic [top_pkg::TL_DUW-1:0] tl_d2h_d_user; 27 | logic tl_d2h_d_error; 28 | 29 | logic tl_d2h_a_ready; 30 | 31 | assign tl_h2d_a_valid = tl_h2d.a_valid; 32 | assign tl_h2d_a_opcode = tl_h2d.a_opcode; 33 | assign tl_h2d_a_param = tl_h2d.a_param; 34 | assign tl_h2d_a_size = tl_h2d.a_size; 35 | assign tl_h2d_a_source = tl_h2d.a_source; 36 | assign tl_h2d_a_address = tl_h2d.a_address; 37 | assign tl_h2d_a_mask = tl_h2d.a_mask; 38 | assign tl_h2d_a_data = tl_h2d.a_data; 39 | assign tl_h2d_a_user = tl_h2d.a_user; 40 | assign tl_h2d_d_ready = tl_h2d.d_ready; 41 | 42 | assign tl_d2h_d_valid = tl_d2h.d_valid; 43 | assign tl_d2h_d_opcode = tl_d2h.d_opcode; 44 | assign tl_d2h_d_param = tl_d2h.d_param; 45 | assign tl_d2h_d_size = tl_d2h.d_size; 46 | assign tl_d2h_d_source = tl_d2h.d_source; 47 | assign tl_d2h_d_sink = tl_d2h.d_sink; 48 | assign tl_d2h_d_data = tl_d2h.d_data; 49 | assign tl_d2h_d_user = tl_d2h.d_user; 50 | assign tl_d2h_d_error = tl_d2h.d_error; 51 | assign tl_d2h_a_ready = tl_d2h.a_ready; 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /hw/prim/prim_ram_1p.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | `ifndef PRIM_DEFAULT_IMPL 8 | `define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric 9 | `endif 10 | 11 | // This is to prevent AscentLint warnings in the generated 12 | // abstract prim wrapper. These warnings occur due to the .* 13 | // use. TODO: we may want to move these inline waivers 14 | // into a separate, generated waiver file for consistency. 15 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 16 | module prim_ram_1p 17 | import prim_ram_1p_pkg::*; 18 | #( 19 | 20 | parameter int Width = 32, // bit 21 | parameter int Depth = 128, 22 | parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask 23 | parameter MemInitFile = "", // VMEM file to initialize the memory with 24 | 25 | localparam int Aw = $clog2(Depth) // derived parameter 26 | 27 | ) ( 28 | input logic clk_i, 29 | 30 | input logic req_i, 31 | input logic write_i, 32 | input logic [Aw-1:0] addr_i, 33 | input logic [Width-1:0] wdata_i, 34 | input logic [Width-1:0] wmask_i, 35 | output logic [Width-1:0] rdata_o, // Read data. Data is returned one cycle after req_i is high. 36 | input ram_1p_cfg_t cfg_i 37 | ); 38 | parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL; 39 | 40 | if (Impl == prim_pkg::ImplLambdalib) begin : gen_lambdalib 41 | prim_lambdalib_ram_1p #( 42 | .DataBitsPerMask(DataBitsPerMask), 43 | .Depth(Depth), 44 | .MemInitFile(MemInitFile), 45 | .Width(Width) 46 | ) u_impl_lambdalib ( 47 | .* 48 | ); 49 | end else begin : gen_generic 50 | prim_generic_ram_1p #( 51 | .DataBitsPerMask(DataBitsPerMask), 52 | .Depth(Depth), 53 | .MemInitFile(MemInitFile), 54 | .Width(Width) 55 | ) u_impl_generic ( 56 | .* 57 | ); 58 | 59 | end 60 | 61 | endmodule 62 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 63 | -------------------------------------------------------------------------------- /openroad/padring.tcl: -------------------------------------------------------------------------------- 1 | # Create false IO sites, since sky130 does not have PAD sites available 2 | make_fake_io_site -name IO_SITE -width 1 -height 200 3 | make_fake_io_site -name IO_CSITE -width 200 -height 204 4 | 5 | # Create IO Rows 6 | make_io_sites -horizontal_site IO_SITE -vertical_site IO_SITE -corner_site IO_CSITE -offset 10 \ 7 | -rotation_horizontal R180 \ 8 | -rotation_vertical R180 \ 9 | -rotation_corner R180 \ 10 | 11 | # Place pads 12 | proc soc_get_pad_cells {side} { 13 | set cells [get_cells -quiet */i${side}/ipad[*].*] 14 | 15 | set insts [] 16 | set i 0 17 | while { [llength $insts] != [llength $cells] } { 18 | foreach type "gpio iovdd* iovss*" { 19 | set cell [get_cells -quiet */i${side}/ipad[$i].*/${type}] 20 | if {[llength $cell] != 0} { 21 | break 22 | } 23 | } 24 | incr i 25 | if { $i > 100 } { 26 | break 27 | } 28 | if {[llength $cell] == 0} { 29 | continue 30 | } 31 | lappend insts [[sta::sta_to_db_inst $cell] getName] 32 | } 33 | 34 | return $insts 35 | } 36 | 37 | # Handle north 38 | puts "Place north edge" 39 | place_pads -row IO_NORTH [soc_get_pad_cells north] 40 | 41 | # Handle south 42 | puts "Place south edge" 43 | place_pads -row IO_SOUTH [soc_get_pad_cells south] 44 | 45 | # Handle west 46 | puts "Place west edge" 47 | place_pads -row IO_WEST [lreverse [soc_get_pad_cells west]] 48 | 49 | # Handle east 50 | puts "Place east edge" 51 | place_pads -row IO_EAST [lreverse [soc_get_pad_cells east]] 52 | 53 | # Place corners 54 | place_corners sky130_ef_io__corner_pad 55 | 56 | # Place IO fill 57 | set iofill [dict get $sc_cfg library sky130io asic cells filler] 58 | place_io_fill -row IO_NORTH {*}$iofill 59 | place_io_fill -row IO_SOUTH {*}$iofill 60 | place_io_fill -row IO_WEST {*}$iofill 61 | place_io_fill -row IO_EAST {*}$iofill 62 | 63 | # Connect ring signals 64 | connect_by_abutment 65 | 66 | # Add bond pads 67 | place_bondpad -bond sky130_ef_io__bare_pad padring/*.i0/gpio -offset "12.5 115" 68 | place_bondpad -bond sky130_ef_io__bare_pad padring/*.i0/io* -offset "8 95" 69 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | pull_request: 4 | schedule: 5 | - cron: '0 8 * * *' 6 | 7 | name: 'CI' 8 | 9 | defaults: 10 | run: 11 | shell: bash 12 | 13 | env: 14 | REGISTRY: ghcr.io 15 | 16 | jobs: 17 | docker_image: 18 | uses: siliconcompiler/siliconcompiler/.github/workflows/docker_image.yml@main 19 | with: 20 | tool: 'tools' 21 | 22 | flat: 23 | name: 'flat' 24 | needs: docker_image 25 | timeout-minutes: 180 26 | runs-on: ubuntu-latest 27 | container: 28 | image: ${{ needs.docker_image.outputs.sc_tool }} 29 | 30 | steps: 31 | - uses: actions/checkout@v6 32 | 33 | - uses: actions/checkout@v6 34 | with: 35 | repository: siliconcompiler/siliconcompiler 36 | path: siliconcompiler 37 | 38 | - run: apt install python3-venv 39 | - name: Run test 40 | run: | 41 | python3 -m venv ./clean_env --clear 42 | source ./clean_env/bin/activate 43 | echo $VIRTUAL_ENV 44 | pip3 install -r python-requirements.txt 45 | pip3 install ./siliconcompiler 46 | ./make.py --top-flat 47 | 48 | - name: Upload image artifacts 49 | uses: actions/upload-artifact@v5 50 | with: 51 | name: flat 52 | path: build/zerosoc/job0/zerosoc.png 53 | 54 | hierarchical: 55 | name: 'hierarchical' 56 | if: false 57 | needs: docker_image 58 | timeout-minutes: 180 59 | runs-on: ubuntu-latest 60 | container: 61 | image: ${{ needs.docker_image.outputs.sc_tool }} 62 | 63 | steps: 64 | - uses: actions/checkout@v6 65 | 66 | - uses: actions/checkout@v6 67 | with: 68 | repository: siliconcompiler/siliconcompiler 69 | path: siliconcompiler 70 | 71 | - run: apt install python3-venv 72 | 73 | - name: Run test 74 | run: | 75 | python3 -m venv ./clean_env --clear 76 | source ./clean_env/bin/activate 77 | echo $VIRTUAL_ENV 78 | pip3 install -r python-requirements.txt 79 | pip3 install ./siliconcompiler 80 | ./make.py --core-only 81 | ./make.py --top-only 82 | 83 | - name: Upload image artifacts 84 | uses: actions/upload-artifact@v5 85 | with: 86 | name: hierarchical 87 | path: | 88 | build/zerosoc_core/job0/zerosoc_core.png 89 | build/zerosoc_top/job0/zerosoc_top.png 90 | -------------------------------------------------------------------------------- /hw/prim/prim_flash.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | 8 | // This is to prevent AscentLint warnings in the generated 9 | // abstract prim wrapper. These warnings occur due to the .* 10 | // use. TODO: we may want to move these inline waivers 11 | // into a separate, generated waiver file for consistency. 12 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 13 | module prim_flash 14 | 15 | #( 16 | 17 | parameter int NumBanks = 2, // number of banks 18 | parameter int InfosPerBank = 1, // info pages per bank 19 | parameter int InfoTypes = 1, // different info types 20 | parameter int InfoTypesWidth = 1, // different info types 21 | parameter int PagesPerBank = 256,// data pages per bank 22 | parameter int WordsPerPage = 256,// words per page 23 | parameter int DataWidth = 32, // bits per word 24 | parameter int MetaDataWidth = 12, // metadata such as ECC 25 | parameter int TestModeWidth = 2 26 | 27 | ) ( 28 | input clk_i, 29 | input rst_ni, 30 | input flash_phy_pkg::flash_phy_prim_flash_req_t [NumBanks-1:0] flash_req_i, 31 | output flash_phy_pkg::flash_phy_prim_flash_rsp_t [NumBanks-1:0] flash_rsp_o, 32 | output logic [flash_phy_pkg::ProgTypes-1:0] prog_type_avail_o, 33 | output init_busy_o, 34 | input tck_i, 35 | input tdi_i, 36 | input tms_i, 37 | output logic tdo_o, 38 | input lc_ctrl_pkg::lc_tx_t bist_enable_i, 39 | input lc_ctrl_pkg::lc_tx_t scanmode_i, 40 | input scan_en_i, 41 | input scan_rst_ni, 42 | input flash_power_ready_h_i, 43 | input flash_power_down_h_i, 44 | inout [TestModeWidth-1:0] flash_test_mode_a_io, 45 | inout flash_test_voltage_h_io, 46 | output logic flash_err_o, 47 | output ast_pkg::ast_dif_t fl_alert_src_o, 48 | input tlul_pkg::tl_h2d_t tl_i, 49 | output tlul_pkg::tl_d2h_t tl_o, 50 | input devmode_i 51 | ); 52 | 53 | if (1) begin : gen_generic 54 | prim_generic_flash #( 55 | .MetaDataWidth(MetaDataWidth), 56 | .DataWidth(DataWidth), 57 | .WordsPerPage(WordsPerPage), 58 | .InfoTypesWidth(InfoTypesWidth), 59 | .InfoTypes(InfoTypes), 60 | .PagesPerBank(PagesPerBank), 61 | .NumBanks(NumBanks), 62 | .InfosPerBank(InfosPerBank), 63 | .TestModeWidth(TestModeWidth) 64 | ) u_impl_generic ( 65 | .* 66 | ); 67 | 68 | end 69 | 70 | endmodule 71 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CI](https://github.com/siliconcompiler/zerosoc/actions/workflows/ci.yml/badge.svg)](https://github.com/siliconcompiler/zerosoc/actions/workflows/ci.yml) 2 | 3 | # ZeroSoC 4 | 5 | ZeroSoC is a RISC-V SoC designed to demonstrate the capabilities of 6 | [SiliconCompiler][sc]. ZeroSoC consists of an [Ibex core][ibex], UART and GPIO 7 | peripherals from the [OpenTitan][opentitan] project, and 8 KB of RAM. 8 | 9 |

10 | 11 |

12 | 13 | ## Getting Started 14 | 15 | Clone the repository and all its submodules: 16 | 17 | ```console 18 | $ git clone git@github.com:siliconcompiler/zerosoc.git 19 | $ cd zerosoc 20 | $ git checkout stable 21 | $ git submodule update --init --recursive 22 | $ pip install -r python-requirements.txt 23 | ``` 24 | 25 | Building ZeroSoC locally for ASIC or FPGA targets requires installing external 26 | tools. This [page][tools] contains links to installation instructions for SC's 27 | supported tools. The build script also supports remote builds, which do not 28 | require installing additional tools. 29 | 30 | **Note**: The ZeroSoC tip of main is considered unstable and may not be 31 | compatible with the latest SiliconCompiler. To ensure compatibility, we 32 | recommend checking out the [`stable`][stable] tag and using the most recent 33 | release version of SC. 34 | 35 | ## Usage 36 | 37 | [`build.py`](build.py) is ZeroSoC's build script, based around the SiliconCompiler Python 38 | API. Running this script with no options initiates a local ZeroSoC ASIC build, 39 | and runs DRC and LVS on the final GDS. 40 | 41 | Running `build.py --help` gives information on additional options: 42 | 43 | ``` 44 | -h, --help show this help message and exit 45 | --core-only Only build ASIC core GDS. 46 | --top-only Only integrate ASIC core into padring. Assumes core already built. 47 | --floorplan Break in floorplanning steps 48 | --verify Run DRC and LVS. 49 | --remote Run on remote server. Requires SC remote credentials. 50 | ``` 51 | 52 | ## FPGA 53 | 54 | For more details on how to run the ZeroSoC FPGA demo, see [here](docs/fpga.md). 55 | 56 | ## License 57 | 58 | [Apache License 2.0](LICENSE) 59 | 60 | [sc]: https://github.com/siliconcompiler/siliconcompiler 61 | [ibex]: https://github.com/lowrisc/ibex 62 | [opentitan]: https://github.com/lowrisc/opentitan 63 | [tutorial]: https://docs.siliconcompiler.com/en/latest/tutorials/zerosoc.html 64 | [tools]: https://docs.siliconcompiler.com/en/latest/reference_manual/tools.html 65 | [stable]: https://github.com/siliconcompiler/zerosoc/tree/stable 66 | -------------------------------------------------------------------------------- /hw/xbar.sv: -------------------------------------------------------------------------------- 1 | module xbar ( 2 | input clk_i, 3 | input rst_ni, 4 | input tlul_pkg::tl_h2d_t tl_corei_i, 5 | output tlul_pkg::tl_d2h_t tl_corei_o, 6 | input tlul_pkg::tl_h2d_t tl_cored_i, 7 | output tlul_pkg::tl_d2h_t tl_cored_o, 8 | output tlul_pkg::tl_h2d_t tl_ram_o, 9 | input tlul_pkg::tl_d2h_t tl_ram_i, 10 | output tlul_pkg::tl_h2d_t tl_uart_o, 11 | input tlul_pkg::tl_d2h_t tl_uart_i, 12 | output tlul_pkg::tl_h2d_t tl_gpio_o, 13 | input tlul_pkg::tl_d2h_t tl_gpio_i 14 | ); 15 | import tlul_pkg::*; 16 | import xbar_pkg::*; 17 | 18 | tl_h2d_t tl_dmem_out_arb_h2d [3]; 19 | tl_d2h_t tl_dmem_out_arb_d2h [3]; 20 | tl_h2d_t tl_ram_in_arb_h2d [2]; 21 | tl_d2h_t tl_ram_in_arb_d2h [2]; 22 | 23 | assign tl_ram_in_arb_h2d[0] = tl_dmem_out_arb_h2d[0]; 24 | assign tl_dmem_out_arb_d2h[0] = tl_ram_in_arb_d2h[0]; 25 | assign tl_ram_in_arb_h2d[1] = tl_corei_i; 26 | assign tl_corei_o = tl_ram_in_arb_d2h[1]; 27 | 28 | assign tl_gpio_o = tl_dmem_out_arb_h2d[1]; 29 | assign tl_dmem_out_arb_d2h[1] = tl_gpio_i; 30 | assign tl_uart_o = tl_dmem_out_arb_h2d[2]; 31 | assign tl_dmem_out_arb_d2h[2] = tl_uart_i; 32 | 33 | logic [1:0] dev_sel_dmem_out_arb; 34 | 35 | always_comb begin 36 | // default steering to generate error response if address is not within the range 37 | dev_sel_dmem_out_arb = 2'd3; 38 | if ((tl_cored_i.a_address & ~(ADDR_MASK_RAM)) == ADDR_SPACE_RAM) begin 39 | dev_sel_dmem_out_arb = 2'd0; 40 | end else if ((tl_cored_i.a_address & ~(ADDR_MASK_GPIO)) == ADDR_SPACE_GPIO) begin 41 | dev_sel_dmem_out_arb = 2'd1; 42 | end else if ((tl_cored_i.a_address & ~(ADDR_MASK_UART)) == ADDR_SPACE_UART) begin 43 | dev_sel_dmem_out_arb = 2'd2; 44 | end 45 | end 46 | 47 | tlul_socket_1n #( 48 | .HReqDepth (4'h0), 49 | .HRspDepth (4'h0), 50 | .DReqDepth (16'h0), 51 | .DRspDepth (16'h0), 52 | .N (3) 53 | ) dmem_out_arb ( 54 | .clk_i (clk_i), 55 | .rst_ni (rst_ni), 56 | .tl_h_i (tl_cored_i), 57 | .tl_h_o (tl_cored_o), 58 | .tl_d_o (tl_dmem_out_arb_h2d), 59 | .tl_d_i (tl_dmem_out_arb_d2h), 60 | .dev_select_i (dev_sel_dmem_out_arb) 61 | ); 62 | 63 | tlul_socket_m1 #( 64 | .HReqDepth (12'h0), 65 | .HRspDepth (12'h0), 66 | .DReqDepth (4'h0), 67 | .DRspDepth (4'h0), 68 | .M (2) 69 | ) ram_in_arb ( 70 | .clk_i (clk_i), 71 | .rst_ni (rst_ni), 72 | .tl_h_i (tl_ram_in_arb_h2d), 73 | .tl_h_o (tl_ram_in_arb_d2h), 74 | .tl_d_i (tl_ram_i), 75 | .tl_d_o (tl_ram_o) 76 | ); 77 | 78 | endmodule 79 | -------------------------------------------------------------------------------- /hw/prim/prim_otp.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // This file is auto-generated. 6 | 7 | 8 | // This is to prevent AscentLint warnings in the generated 9 | // abstract prim wrapper. These warnings occur due to the .* 10 | // use. TODO: we may want to move these inline waivers 11 | // into a separate, generated waiver file for consistency. 12 | //ri lint_check_off OUTPUT_NOT_DRIVEN INPUT_NOT_READ 13 | module prim_otp 14 | import prim_otp_pkg::*; 15 | #( 16 | 17 | // Native OTP word size. This determines the size_i granule. 18 | parameter int Width = 16, 19 | parameter int Depth = 1024, 20 | // This determines the maximum number of native words that 21 | // can be transferred accross the interface in one cycle. 22 | parameter int SizeWidth = 2, 23 | // Width of the power sequencing signal. 24 | parameter int PwrSeqWidth = 2, 25 | // Number of Test TL-UL words 26 | parameter int TlDepth = 16, 27 | // Derived parameters 28 | localparam int AddrWidth = prim_util_pkg::vbits(Depth), 29 | localparam int IfWidth = 2**SizeWidth*Width, 30 | // VMEM file to initialize the memory with 31 | parameter MemInitFile = "" 32 | 33 | ) ( 34 | input clk_i, 35 | input rst_ni, 36 | // Macro-specific power sequencing signals to/from AST 37 | output logic [PwrSeqWidth-1:0] pwr_seq_o, 38 | input [PwrSeqWidth-1:0] pwr_seq_h_i, 39 | // Test interface 40 | input tlul_pkg::tl_h2d_t test_tl_i, 41 | output tlul_pkg::tl_d2h_t test_tl_o, 42 | // Ready valid handshake for read/write command 43 | output logic ready_o, 44 | input valid_i, 45 | input [SizeWidth-1:0] size_i, // #(Native words)-1, e.g. size == 0 for 1 native word. 46 | input cmd_e cmd_i, // 00: read command, 01: write command, 11: init command 47 | input [AddrWidth-1:0] addr_i, 48 | input [IfWidth-1:0] wdata_i, 49 | // Response channel 50 | output logic valid_o, 51 | output logic [IfWidth-1:0] rdata_o, 52 | output err_e err_o, 53 | // External programming voltage 54 | inout wire ext_voltage_io, //TODO enable it after the change in prim_otp file 55 | input ext_voltage_en_i, // TODO 56 | //// alert indication 57 | ////////////////////////// 58 | output ast_pkg::ast_dif_t otp_alert_src_o, 59 | 60 | // Scan 61 | input lc_ctrl_pkg::lc_tx_t scanmode_i, // Scan Mode input 62 | input scan_en_i, // Scan Shift 63 | input scan_rst_ni // Scan Reset 64 | ); 65 | 66 | if (1) begin : gen_generic 67 | prim_generic_otp #( 68 | .Depth(Depth), 69 | .TlDepth(TlDepth), 70 | .PwrSeqWidth(PwrSeqWidth), 71 | .SizeWidth(SizeWidth), 72 | .MemInitFile(MemInitFile), 73 | .Width(Width) 74 | ) u_impl_generic ( 75 | .* 76 | ); 77 | 78 | end 79 | 80 | endmodule 81 | //ri lint_check_on OUTPUT_NOT_DRIVEN INPUT_NOT_READ 82 | -------------------------------------------------------------------------------- /opentitan.py: -------------------------------------------------------------------------------- 1 | from siliconcompiler import Library 2 | 3 | 4 | def setup(): 5 | lib = Library("opentitan", package='opentitan', auto_enable=True) 6 | lib.register_source( 7 | name='opentitan', 8 | path='git+https://github.com/lowRISC/opentitan.git', 9 | ref='8b9fe4bf2db8ccfac0b26600decf07cf41867e07') 10 | 11 | # Include dirs 12 | lib.add('option', 'idir', 'hw/ip/prim/rtl') 13 | lib.add('option', 'idir', 'hw/dv/sv/dv_utils') 14 | 15 | # Add RTL of all modules we use to search path 16 | lib.add('option', 'ydir', 'hw/ip/tlul/rtl') 17 | lib.add('option', 'ydir', 'hw/ip/rv_core_ibex/rtl') 18 | lib.add('option', 'ydir', 'hw/ip/uart/rtl') 19 | lib.add('option', 'ydir', 'hw/ip/gpio/rtl') 20 | lib.add('option', 'ydir', 'hw/ip/prim/rtl') 21 | lib.add('option', 'ydir', 'hw/ip/prim_generic/rtl') 22 | 23 | # SV packages (need to be added explicitly) 24 | lib.input('hw/top_earlgrey/rtl/top_pkg.sv') 25 | 26 | lib.input('hw/ip/gpio/rtl/gpio_reg_pkg.sv') 27 | lib.input('hw/ip/uart/rtl/uart_reg_pkg.sv') 28 | lib.input('hw/ip/prim/rtl/prim_alert_pkg.sv') 29 | lib.input('hw/ip/prim/rtl/prim_esc_pkg.sv') 30 | lib.input('hw/ip/prim/rtl/prim_otp_pkg.sv') 31 | lib.input('hw/ip/prim/rtl/prim_pad_wrapper_pkg.sv') 32 | lib.input('hw/ip/prim/rtl/prim_ram_1p_pkg.sv') 33 | lib.input('hw/ip/prim/rtl/prim_ram_2p_pkg.sv') 34 | lib.input('hw/ip/prim/rtl/prim_rom_pkg.sv') 35 | lib.input('hw/ip/tlul/rtl/tlul_pkg.sv') 36 | 37 | lib.input('hw/ip/prim/rtl/prim_util_pkg.sv') 38 | lib.input('hw/ip/prim/rtl/prim_secded_pkg.sv') 39 | 40 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv') 41 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_top.sv') 42 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_core.sv') 43 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv') 44 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv') 45 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv') 46 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv') 47 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv') 48 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv') 49 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv') 50 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv') 51 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv') 52 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_csr.sv') 53 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv') 54 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv') 55 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv') 56 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv') 57 | 58 | lib.input('hw/ip/lc_ctrl/rtl/lc_ctrl_state_pkg.sv') 59 | lib.input('hw/ip/lc_ctrl/rtl/lc_ctrl_pkg.sv') 60 | 61 | # Hack to work around Yosys + Surelog issue. Even though this is found in 62 | # one of our ydirs, we get different synthesis results if this isn't ordered 63 | # earlier. 64 | lib.input('hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv') 65 | 66 | return lib 67 | -------------------------------------------------------------------------------- /sw/lib/zerosoc.c: -------------------------------------------------------------------------------- 1 | #include "zerosoc.h" 2 | 3 | #include "sw/device/lib/dif/dif_gpio.h" 4 | #include "sw/device/lib/dif/dif_uart.h" 5 | 6 | #define CLOCK_FREQ 6000000ULL 7 | #define RAM_BASE_ADDR 0x00000000 8 | #define UART_BASE_ADDR 0x40000000 9 | #define GPIO_BASE_ADDR 0x40010000 10 | 11 | bool init_peripherals(zerosoc_t *soc) { 12 | dif_gpio_params_t gpio_params = { mmio_region_from_addr(GPIO_BASE_ADDR) }; 13 | if (dif_gpio_init(gpio_params, &soc->gpio) != kDifGpioOk) 14 | return false; 15 | 16 | dif_uart_params_t uart_params = { mmio_region_from_addr(UART_BASE_ADDR) }; 17 | if (dif_uart_init(uart_params, &soc->uart) != kDifUartOk) 18 | return false; 19 | 20 | dif_uart_config_t config; 21 | config.baudrate = 9600; 22 | config.clk_freq_hz = CLOCK_FREQ; 23 | config.parity_enable = kDifUartToggleDisabled; 24 | config.parity = kDifUartParityEven; 25 | 26 | if (dif_uart_configure(&soc->uart, config) != kDifUartOk) 27 | return false; 28 | 29 | return true; 30 | } 31 | 32 | bool gpio_read(zerosoc_t *soc, int pin) { 33 | bool state; 34 | dif_gpio_result_t res = dif_gpio_read(&soc->gpio, pin, &state); 35 | return state; 36 | } 37 | 38 | void gpio_write(zerosoc_t *soc, int pin, bool state) { 39 | dif_gpio_result_t res = dif_gpio_write(&soc->gpio, pin, state); 40 | } 41 | 42 | size_t uart_write(zerosoc_t *soc, const char *buf, size_t len) { 43 | for (size_t i = 0; i < len; ++i) { 44 | if (dif_uart_byte_send_polled(&soc->uart, (uint8_t)buf[i]) != kDifUartOk) { 45 | return i; 46 | } 47 | } 48 | return len; 49 | } 50 | 51 | size_t uart_read(zerosoc_t *soc, char *buf, size_t max_len) { 52 | size_t i; 53 | for (i = 0; i < max_len; i++) { 54 | if (dif_uart_byte_receive_polled(&soc->uart, (uint8_t*) &buf[i]) != kDifUartOk) 55 | return i; 56 | 57 | if (buf[i] == '\r' || buf[i] == '\n') { 58 | // return i instead of i+1 to trim newline 59 | return i; 60 | } 61 | } 62 | return i; 63 | } 64 | 65 | size_t uart_bytes_available(zerosoc_t *soc) { 66 | size_t bytes; 67 | if (dif_uart_rx_bytes_available(&soc->uart, &bytes) != kDifUartOk) 68 | return -1; 69 | 70 | return bytes; 71 | } 72 | 73 | void delay(unsigned long msec) { 74 | unsigned long usec_cycles = (CLOCK_FREQ / 1000 / 8) * msec; 75 | 76 | int out; /* only to notify compiler of modifications to |loops| */ 77 | asm volatile( 78 | "1: nop \n" // 1 cycle 79 | " nop \n" // 1 cycle 80 | " nop \n" // 1 cycle 81 | " nop \n" // 1 cycle 82 | " addi %1, %1, -1 \n" // 1 cycle 83 | " bnez %1, 1b \n" // 3 cycles 84 | : "=&r" (out) 85 | : "0" (usec_cycles) 86 | ); 87 | } 88 | 89 | uint64_t mcycle_read(void) { 90 | uint32_t cycle_low = 0; 91 | uint32_t cycle_high = 0; 92 | uint32_t cycle_high_2 = 0; 93 | asm volatile( 94 | "read%=:" 95 | " csrr %0, mcycleh;" // Read `mcycleh`. 96 | " csrr %1, mcycle;" // Read `mcycle`. 97 | " csrr %2, mcycleh;" // Read `mcycleh` again. 98 | " bne %0, %2, read%=;" // Try again if `mcycle` overflowed before 99 | // reading `mcycleh`. 100 | : "+r"(cycle_high), "=r"(cycle_low), "+r"(cycle_high_2) 101 | :); 102 | return (uint64_t)cycle_high << 32 | cycle_low; 103 | } 104 | 105 | uint64_t millis() { 106 | uint64_t cycles = mcycle_read(); 107 | return cycles / (CLOCK_FREQ / 1000); 108 | } 109 | -------------------------------------------------------------------------------- /sw/ram.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * ZeroSoC linker script 3 | * 4 | * Roughly based on OpenTitan's boot ROM linker script, with modifications for 5 | * our purposes. 6 | * https://github.com/lowRISC/opentitan/blob/master/sw/device/boot_rom/rom_link.ld 7 | */ 8 | 9 | /** 10 | * Link libgcc statically into address space 11 | */ 12 | GROUP(-lgcc) 13 | 14 | /** 15 | * Indicate that there are no dynamic libraries, whatsoever. 16 | */ 17 | __DYNAMIC = 0; 18 | 19 | _ram_size = 8k; 20 | 21 | /** 22 | * Fixed-size stack at end of RAM 23 | */ 24 | _stack_size = 200; 25 | _stack_end = _ram_size; 26 | _stack_start = _stack_end - _stack_size; 27 | 28 | MEMORY { 29 | ram (rwx): ORIGIN = 0, LENGTH = _ram_size - _stack_size 30 | ram_stack (rw): ORIGIN = _ram_size - _stack_size, LENGTH = _stack_size 31 | } 32 | 33 | SECTIONS { 34 | /** 35 | * Standard text section, containing program code. 36 | */ 37 | .text : ALIGN(4) { 38 | *(.text) 39 | *(.text.*) 40 | } > ram 41 | 42 | /** 43 | * Read-only data section, containing all large compile-time constants, like 44 | * strings. 45 | */ 46 | .rodata : ALIGN(4) { 47 | /* Small read-only data comes before regular read-only data for the same 48 | * reasons as in the data section */ 49 | *(.srodata) 50 | *(.srodata.*) 51 | *(.rodata) 52 | *(.rodata.*) 53 | } > ram 54 | 55 | /** 56 | * "Intitial data" section, the initial values of the mutable data section 57 | * initialized at runtime. 58 | */ 59 | .idata : ALIGN(4) { 60 | _data_init_start = .; 61 | } > ram 62 | 63 | /** 64 | * Standard mutable data section. 65 | * TODO: this may need to be set up in code. 66 | */ 67 | .data : ALIGN(4) { 68 | _data_start = .; 69 | __global_pointer$ = . + 2048; 70 | 71 | /* Small data should come before larger data. This helps to ensure small 72 | * globals are within 2048 bytes of the value of `gp`, making their accesses 73 | * hopefully only take one instruction. */ 74 | *(.sdata) 75 | *(.sdata.*) 76 | 77 | /* Other data will likely need multiple instructions to load, so we're less 78 | * concerned about address materialisation taking more than one instruction. 79 | */ 80 | *(.data) 81 | *(.data.*) 82 | . = ALIGN(4); 83 | _data_end = .; 84 | } > ram 85 | 86 | /** 87 | * Standard BSS section. 88 | * TODO: should this be zeroed in code? 89 | */ 90 | .bss : ALIGN(4) { 91 | _bss_start = .; 92 | /* Small BSS comes before regular BSS for the same reasons as in the data 93 | * section */ 94 | *(.sbss) 95 | *(.sbss.*) 96 | *(.bss) 97 | *(.bss.*) 98 | . = ALIGN(4); 99 | _bss_end = .; 100 | } > ram 101 | 102 | /* Discarded Sections (Not needed in device images). */ 103 | /DISCARD/ : { 104 | /* We don't keep unwind information */ 105 | *(.eh_frame) 106 | *(.eh_frame_hdr) 107 | 108 | /* Compiler Information */ 109 | *(.comment) 110 | *(.comment.*) 111 | 112 | /* Other Notes */ 113 | *(.note) 114 | *(.note.*) 115 | 116 | /* Relocations */ 117 | *(.rela.*) 118 | *(.rela.dyn) 119 | 120 | /* STAB Debugging Info */ 121 | *(.stab) 122 | *(.stab.*) 123 | *(.stabstr) 124 | 125 | /* Debug info */ 126 | *(.debug_info) 127 | *(.debug_abbrev) 128 | *(.debug_aranges) 129 | *(.debug_line) 130 | *(.debug_loc) 131 | *(.debug_ranges) 132 | *(.debug_str) 133 | *(.debug_frame) 134 | 135 | /* COMMON Sections */ 136 | *(COMMON) 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /hw/asic_top.v: -------------------------------------------------------------------------------- 1 | module asic_top ( 2 | inout vdd, 3 | inout vss, 4 | inout vddio, 5 | inout vssio, 6 | 7 | inout [8:0] no_pad, 8 | inout [8:0] so_pad, 9 | inout [8:0] ea_pad, 10 | inout [8:0] we_pad 11 | ); 12 | 13 | wire [8:0] we_din; 14 | wire [8:0] we_dout; 15 | wire [8:0] we_ie; 16 | wire [8:0] we_oen; 17 | wire [161:0] we_tech_cfg; 18 | 19 | wire [8:0] no_din; 20 | wire [8:0] no_dout; 21 | wire [8:0] no_ie; 22 | wire [8:0] no_oen; 23 | wire [161:0] no_tech_cfg; 24 | 25 | wire [8:0] so_din; 26 | wire [8:0] so_dout; 27 | wire [8:0] so_ie; 28 | wire [8:0] so_oen; 29 | wire [161:0] so_tech_cfg; 30 | 31 | wire [8:0] ea_din; 32 | wire [8:0] ea_dout; 33 | wire [8:0] ea_ie; 34 | wire [8:0] ea_oen; 35 | wire [161:0] ea_tech_cfg; 36 | 37 | asic_core core ( 38 | ._vdd(vdd), 39 | ._vss(vss), 40 | 41 | .we_din, 42 | .we_dout, 43 | .we_ie, 44 | .we_oen, 45 | .we_tech_cfg, 46 | 47 | .no_din, 48 | .no_dout, 49 | .no_ie, 50 | .no_oen, 51 | .no_tech_cfg, 52 | 53 | .so_din, 54 | .so_dout, 55 | .so_ie, 56 | .so_oen, 57 | .so_tech_cfg, 58 | 59 | .ea_din, 60 | .ea_dout, 61 | .ea_ie, 62 | .ea_oen, 63 | .ea_tech_cfg 64 | ); 65 | 66 | //############################# 67 | // PADRING 68 | //############################# 69 | // All IO related "tech" parameters in the .vh file 70 | `include "iomap.vh" 71 | wire [7:0] ioring; 72 | 73 | la_padring #(.RINGW(8), 74 | .CFGW(18), 75 | //north 76 | .NO_NPINS(9), 77 | .NO_NCELLS(13), 78 | .NO_NSECTIONS(1), 79 | .NO_CELLMAP(CELLMAP), 80 | //east 81 | .EA_NPINS(9), 82 | .EA_NCELLS(13), 83 | .EA_NSECTIONS(1), 84 | .EA_CELLMAP(CELLMAP), 85 | //south 86 | .SO_NPINS(9), 87 | .SO_NCELLS(13), 88 | .SO_NSECTIONS(1), 89 | .SO_CELLMAP(CELLMAP), 90 | //west 91 | .WE_NPINS(9), 92 | .WE_NCELLS(13), 93 | .WE_NSECTIONS(1), 94 | .WE_CELLMAP(CELLMAP)) 95 | padring(// Inouts 96 | .no_pad (no_pad), 97 | .ea_pad (ea_pad), 98 | .so_pad (so_pad), 99 | .we_pad (we_pad), 100 | .no_aio (), 101 | .ea_aio (), 102 | .so_aio (), 103 | .we_aio (), 104 | .no_vddio (vddio), 105 | .ea_vddio (vddio), 106 | .so_vddio (vddio), 107 | .we_vddio (vddio), 108 | /*AUTOINST*/ 109 | // Outputs 110 | .no_zp (no_din), 111 | .no_zn (), 112 | .ea_zp (ea_din), 113 | .ea_zn (), 114 | .so_zp (so_din), 115 | .so_zn (), 116 | .we_zp (we_din), 117 | .we_zn (), 118 | // Inouts 119 | .vss (vss), 120 | .no_vdd (vdd), 121 | .no_vssio (vssio), 122 | .no_ioring (ioring), 123 | .ea_vdd (vdd), 124 | .ea_vssio (vssio), 125 | .ea_ioring (ioring), 126 | .so_vdd (vdd), 127 | .so_vssio (vssio), 128 | .so_ioring (ioring), 129 | .we_vdd (vdd), 130 | .we_vssio (vssio), 131 | .we_ioring (ioring), 132 | // Inputs 133 | .no_a (no_dout), 134 | .no_ie (no_ie), 135 | .no_oe (~no_oen), 136 | .no_pe ('b0), 137 | .no_ps ('b0), 138 | .no_cfg (no_tech_cfg), 139 | .ea_a (ea_dout), 140 | .ea_ie (ea_ie), 141 | .ea_oe (~ea_oen), 142 | .ea_pe ('b0), 143 | .ea_ps ('b0), 144 | .ea_cfg (ea_tech_cfg), 145 | .so_a (so_dout), 146 | .so_ie (so_ie), 147 | .so_oe (~so_oen), 148 | .so_pe ('b0), 149 | .so_ps ('b0), 150 | .so_cfg (so_tech_cfg), 151 | .we_a (we_dout), 152 | .we_ie (we_ie), 153 | .we_oe (~we_oen), 154 | .we_pe ('b0), 155 | .we_ps ('b0), 156 | .we_cfg (we_tech_cfg)); 157 | 158 | endmodule 159 | -------------------------------------------------------------------------------- /hw/zerosoc.sv: -------------------------------------------------------------------------------- 1 | module zerosoc #( 2 | parameter bit IbexPipeLine = 0, 3 | parameter [31:0] BootAddr = 32'b0, 4 | // TODO: need to hard code file until https://github.com/zachjs/sv2v/issues/147 is resolved 5 | parameter RamInitFile = "sw/hello.mem", 6 | parameter RamDepth = 512, 7 | parameter ASIC = 1 8 | ) ( 9 | // Clock and Reset 10 | input clk_i, 11 | input rst_ni, 12 | 13 | input uart_rx_i, 14 | output logic uart_tx_o, 15 | output logic uart_tx_en_o, 16 | 17 | input [31:0] gpio_i, 18 | output [31:0] gpio_o, 19 | output [31:0] gpio_en_o 20 | ); 21 | 22 | import tlul_pkg::*; 23 | 24 | tl_h2d_t tl_corei_h_h2d; 25 | tl_d2h_t tl_corei_h_d2h; 26 | 27 | tl_h2d_t tl_cored_h_h2d; 28 | tl_d2h_t tl_cored_h_d2h; 29 | 30 | tl_h2d_t tl_uart_d_h2d; 31 | tl_d2h_t tl_uart_d_d2h; 32 | 33 | tl_h2d_t tl_gpio_d_h2d; 34 | tl_d2h_t tl_gpio_d_d2h; 35 | 36 | tl_h2d_t tl_ram_d_h2d; 37 | tl_d2h_t tl_ram_d_d2h; 38 | 39 | tl_h2d_t tl_xbar_h_h2d; 40 | tl_d2h_t tl_xbar_h_d2h; 41 | 42 | tl_dbg cored_dbg ( 43 | .tl_h2d(tl_cored_h_h2d), 44 | .tl_d2h(tl_cored_h_d2h) 45 | ); 46 | 47 | rv_core_ibex #( 48 | .PMPEnable (0), 49 | .PMPGranularity (0), // 2^(PMPGranularity+2) == 4 byte granularity 50 | .PMPNumRegions (16), 51 | .MHPMCounterNum (0), 52 | .MHPMCounterWidth (0), 53 | .RV32E (0), 54 | .RV32M (ibex_pkg::RV32MNone), 55 | .RV32B (ibex_pkg::RV32BNone), 56 | .RegFile (ASIC ? ibex_pkg::RegFileLatch : ibex_pkg::RegFileFPGA), 57 | .BranchTargetALU (0), 58 | .WritebackStage (0), 59 | .ICache (0), 60 | .ICacheECC (0), 61 | .BranchPredictor (0), 62 | .DbgTriggerEn (0), 63 | .SecureIbex (0), 64 | // .DmHaltAddr (ADDR_SPACE_DEBUG_MEM + dm::HaltAddress[31:0]), 65 | // .DmExceptionAddr (ADDR_SPACE_DEBUG_MEM + dm::ExceptionAddress[31:0]), 66 | .PipeLine (IbexPipeLine) 67 | ) u_rv_core_ibex ( 68 | // clock and reset 69 | .clk_i (clk_i), 70 | .rst_ni (rst_ni), 71 | // Don't use "escalation receiver" 72 | .clk_esc_i (1'b0), 73 | .rst_esc_ni (1'b1), 74 | 75 | // Unused when ICache is off 76 | .ram_cfg_i ({$bits(prim_ram_1p_pkg::ram_1p_cfg_t){1'b0}}), 77 | 78 | // static pinning 79 | .hart_id_i (32'b0), 80 | .boot_addr_i (BootAddr), 81 | 82 | // TL-UL buses 83 | .tl_i_o (tl_corei_h_h2d), 84 | .tl_i_i (tl_corei_h_d2h), 85 | .tl_d_o (tl_cored_h_h2d), 86 | .tl_d_i (tl_cored_h_d2h), 87 | 88 | // interrupts 89 | .irq_software_i (1'b0), 90 | .irq_timer_i (1'b0), 91 | .irq_external_i (1'b0), 92 | 93 | // escalation input from alert handler (NMI) 94 | .esc_tx_i (1'b0), 95 | .esc_rx_o (), 96 | 97 | // debug interface 98 | .debug_req_i (1'b0), 99 | 100 | // crash dump interface 101 | .crash_dump_o (), 102 | 103 | // CPU control signals -- stay running 104 | .lc_cpu_en_i (lc_ctrl_pkg::On), 105 | .pwrmgr_cpu_en_i (lc_ctrl_pkg::On), 106 | .core_sleep_o (), 107 | 108 | // stay out of test mode 109 | .scan_rst_ni(1'b1), 110 | .scanmode_i(1'b0) 111 | ); 112 | 113 | // sram device 114 | logic ram_req; 115 | logic ram_we; 116 | logic [$clog2(RamDepth)-1:0] ram_addr; 117 | logic [31:0] ram_wdata; 118 | logic [31:0] ram_wmask; 119 | logic [31:0] ram_rdata; 120 | logic ram_rvalid; 121 | 122 | tlul_adapter_sram #( 123 | .SramAw($clog2(RamDepth)), 124 | .SramDw(32), 125 | .Outstanding(1), 126 | .EnableRspIntgGen(1), 127 | .EnableDataIntgGen(1) 128 | ) tl_adapter_ram ( 129 | .clk_i (clk_i), 130 | .rst_ni (rst_ni), 131 | .tl_i (tl_ram_d_h2d), 132 | .tl_o (tl_ram_d_d2h), 133 | .en_ifetch_i(tlul_pkg::InstrEn), // enable requests with "Instruction" type 134 | 135 | .req_o (ram_req), 136 | .req_type_o(), 137 | .gnt_i (1'b1), // Always grant as only one requester exists 138 | .we_o (ram_we), 139 | .addr_o (ram_addr), 140 | .wdata_o (ram_wdata), 141 | .wmask_o (ram_wmask), 142 | .intg_error_o(), 143 | .rdata_i (ram_rdata), 144 | .rvalid_i (ram_rvalid), 145 | .rerror_i (2'b00) 146 | ); 147 | 148 | prim_ram_1p_adv #( 149 | .Width(32), 150 | .Depth(RamDepth), 151 | .DataBitsPerMask(8), 152 | .MemInitFile(RamInitFile) 153 | ) ram ( 154 | .clk_i (clk_i), 155 | .rst_ni (rst_ni), 156 | 157 | .req_i (ram_req), 158 | .write_i (ram_we), 159 | .addr_i (ram_addr), 160 | .wdata_i (ram_wdata), 161 | .wmask_i (ram_wmask), 162 | .rdata_o (ram_rdata), 163 | .rvalid_o (ram_rvalid), 164 | .rerror_o (), // tied to zero, not important 165 | 166 | .cfg_i(8'b0) // currently unused 167 | ); 168 | 169 | gpio gpio ( 170 | .clk_i (clk_i), 171 | .rst_ni (rst_ni), 172 | 173 | // Input 174 | .cio_gpio_i (gpio_i), 175 | 176 | // Output 177 | .cio_gpio_o (gpio_o), 178 | .cio_gpio_en_o (gpio_en_o), 179 | 180 | // Interrupt 181 | .intr_gpio_o (), 182 | 183 | // Inter-module signals 184 | .tl_i(tl_gpio_d_h2d), 185 | .tl_o(tl_gpio_d_d2h) 186 | ); 187 | 188 | uart uart ( 189 | .tl_i (tl_uart_d_h2d), 190 | .tl_o (tl_uart_d_d2h), 191 | 192 | // Input 193 | .cio_rx_i (uart_rx_i), 194 | 195 | // Output 196 | .cio_tx_o (uart_tx_o), 197 | .cio_tx_en_o (uart_tx_en_o), 198 | 199 | // Interrupt 200 | .intr_tx_watermark_o (intr_uart_tx_watermark), 201 | .intr_rx_watermark_o (intr_uart_rx_watermark), 202 | .intr_tx_empty_o (intr_uart_tx_empty), 203 | .intr_rx_overflow_o (intr_uart_rx_overflow), 204 | .intr_rx_frame_err_o (intr_uart_rx_frame_err), 205 | .intr_rx_break_err_o (intr_uart_rx_break_err), 206 | .intr_rx_timeout_o (intr_uart_rx_timeout), 207 | .intr_rx_parity_err_o (intr_uart_rx_parity_err), 208 | 209 | .clk_i (clk_i), 210 | .rst_ni (rst_ni) 211 | ); 212 | 213 | xbar xbar ( 214 | .clk_i (clk_i), 215 | .rst_ni (rst_ni), 216 | 217 | // host interfaces 218 | .tl_corei_i (tl_corei_h_h2d), 219 | .tl_corei_o (tl_corei_h_d2h), 220 | .tl_cored_i (tl_cored_h_h2d), 221 | .tl_cored_o (tl_cored_h_d2h), 222 | 223 | // device interfaces 224 | .tl_ram_i (tl_ram_d_d2h), 225 | .tl_ram_o (tl_ram_d_h2d), 226 | .tl_uart_i (tl_uart_d_d2h), 227 | .tl_uart_o (tl_uart_d_h2d), 228 | .tl_gpio_i (tl_gpio_d_d2h), 229 | .tl_gpio_o (tl_gpio_d_h2d) 230 | ); 231 | 232 | endmodule 233 | -------------------------------------------------------------------------------- /hw/asic_core.v: -------------------------------------------------------------------------------- 1 | module asic_core ( 2 | inout _vdd, 3 | inout _vss, 4 | 5 | input [8:0] we_din, 6 | output [8:0] we_dout, 7 | output [8:0] we_ie, 8 | output [8:0] we_oen, 9 | output [161:0] we_tech_cfg, 10 | 11 | input [8:0] no_din, 12 | output [8:0] no_dout, 13 | output [8:0] no_ie, 14 | output [8:0] no_oen, 15 | output [161:0] no_tech_cfg, 16 | 17 | input [8:0] so_din, 18 | output [8:0] so_dout, 19 | output [8:0] so_ie, 20 | output [8:0] so_oen, 21 | output [161:0] so_tech_cfg, 22 | 23 | input [8:0] ea_din, 24 | output [8:0] ea_dout, 25 | output [8:0] ea_ie, 26 | output [8:0] ea_oen, 27 | output [161:0] ea_tech_cfg 28 | ); 29 | 30 | wire uart_tx; 31 | wire uart_tx_en_o; 32 | 33 | wire [31:0] gpio_in; 34 | wire [31:0] gpio_out; 35 | wire [31:0] gpio_en_o; 36 | 37 | // Instantiate SoC 38 | zerosoc #( 39 | .RamDepth(`RAM_DEPTH), 40 | .ASIC(1) 41 | ) soc ( 42 | .clk_i(clk), 43 | .rst_ni(rst), 44 | 45 | .uart_rx_i(uart_rx), 46 | .uart_tx_o(uart_tx), 47 | .uart_tx_en_o(uart_tx_en_o), 48 | 49 | .gpio_i(gpio_in), 50 | .gpio_o(gpio_out), 51 | .gpio_en_o(gpio_en_o) 52 | ); 53 | 54 | // WEST 55 | assign gpio_in[4:0] = we_din[4:0]; 56 | assign clk = we_din[5]; 57 | assign rst = we_din[6]; 58 | assign uart_rx = we_din[7]; 59 | // we_din[8] unused - uart_tx is an output 60 | 61 | assign we_dout = {uart_tx, 3'b000, gpio_out[4:0]}; 62 | assign we_oen = {~uart_tx_en_o, 3'b111, ~gpio_en_o[4:0]}; 63 | assign we_ie = ~we_oen; // ie is secretly ien for skywater 64 | 65 | // NORTH 66 | assign gpio_in[13:5] = no_din; 67 | assign no_dout = gpio_out[13:5]; 68 | assign no_oen = ~gpio_en_o[13:5]; 69 | assign no_ie = ~no_oen; // ie is secretly ien for skywater 70 | 71 | // EAST 72 | assign gpio_in[22:14] = ea_din; 73 | assign ea_dout = gpio_out[22:14]; 74 | assign ea_oen = ~gpio_en_o[22:14]; 75 | assign ea_ie = ~ea_oen; // ie is secretly ien for skywater 76 | 77 | // SOUTH 78 | assign gpio_in[31:23] = so_din; 79 | assign so_dout = gpio_out[31:23]; 80 | assign so_oen = ~gpio_en_o[31:23]; 81 | assign so_ie = ~so_oen; // ie is secretly ien for skywater 82 | 83 | // Tieoffs 84 | // Note that all enable signals used for power-on ramp are tied off to their 85 | // fixed steady-state values. 86 | generate 87 | genvar i; 88 | 89 | for(i=0;i<9;i=i+1) 90 | begin: we_tieoff 91 | wire tie_lo_esd, tie_hi_esd; 92 | assign tie_lo_esd = we_tech_cfg[i*18 + 16]; 93 | assign tie_hi_esd = we_tech_cfg[i*18 + 17]; 94 | 95 | assign we_tech_cfg[i*18 + 0] = 1'b1; // hld_h_n 96 | assign we_tech_cfg[i*18 + 1] = 1'b1; // enable_h 97 | assign we_tech_cfg[i*18 + 2] = tie_lo_esd; // enable_inp_h 98 | assign we_tech_cfg[i*18 + 3] = 1'b1; // enable_vdda_h 99 | assign we_tech_cfg[i*18 + 4] = 1'b1; // enable_vswitch_h DIFF!! 100 | assign we_tech_cfg[i*18 + 5] = 1'b1; // enable_vddio 101 | assign we_tech_cfg[i*18 + 6] = 1'b0; // ib_mode_sel 102 | assign we_tech_cfg[i*18 + 7] = 1'b0; // vtrip_sel 103 | assign we_tech_cfg[i*18 + 8] = 1'b0; // slow 104 | assign we_tech_cfg[i*18 + 9] = 1'b0; // hld_ovr 105 | assign we_tech_cfg[i*18 + 10] = 1'b0; // analog_en 106 | assign we_tech_cfg[i*18 + 11] = 1'b0; // analog_sel 107 | assign we_tech_cfg[i*18 + 12] = 1'b0; // analog_pol 108 | // strong pull-up, strong pull-down 109 | assign we_tech_cfg[i*18 + 15:i*18 + 13] = 3'b110; // dm[2:0] 110 | end 111 | 112 | for(i=0;i<9;i=i+1) 113 | begin: no_tieoff 114 | wire tie_lo_esd, tie_hi_esd; 115 | assign tie_lo_esd = no_tech_cfg[i*18 + 16]; 116 | assign tie_hi_esd = no_tech_cfg[i*18 + 17]; 117 | 118 | assign no_tech_cfg[i*18 + 0] = 1'b1; // hld_h_n 119 | assign no_tech_cfg[i*18 + 1] = 1'b1; // enable_h 120 | assign no_tech_cfg[i*18 + 2] = tie_lo_esd; // enable_inp_h 121 | assign no_tech_cfg[i*18 + 3] = 1'b1; // enable_vdda_h 122 | assign no_tech_cfg[i*18 + 4] = 1'b1; // enable_vswitch_h 123 | assign no_tech_cfg[i*18 + 5] = 1'b1; // enable_vddio 124 | assign no_tech_cfg[i*18 + 6] = 1'b0; // ib_mode_sel 125 | assign no_tech_cfg[i*18 + 7] = 1'b0; // vtrip_sel 126 | assign no_tech_cfg[i*18 + 8] = 1'b0; // slow 127 | assign no_tech_cfg[i*18 + 9] = 1'b0; // hld_ovr 128 | assign no_tech_cfg[i*18 + 10] = 1'b0; // analog_en 129 | assign no_tech_cfg[i*18 + 11] = 1'b0; // analog_sel 130 | assign no_tech_cfg[i*18 + 12] = 1'b0; // analog_pol 131 | // strong pull-up, strong pull-down 132 | assign no_tech_cfg[i*18 + 15:i*18 + 13] = 3'b110; // dm[2:0] 133 | end 134 | 135 | for(i=0;i<9;i=i+1) 136 | begin: ea_tieoff 137 | wire tie_lo_esd, tie_hi_esd; 138 | assign tie_lo_esd = ea_tech_cfg[i*18 + 16]; 139 | assign tie_hi_esd = ea_tech_cfg[i*18 + 17]; 140 | 141 | assign ea_tech_cfg[i*18 + 0] = 1'b1; // hld_h_n 142 | assign ea_tech_cfg[i*18 + 1] = 1'b1; // enable_h 143 | assign ea_tech_cfg[i*18 + 2] = tie_lo_esd; // enable_inp_h 144 | assign ea_tech_cfg[i*18 + 3] = 1'b1; // enable_vdda_h 145 | assign ea_tech_cfg[i*18 + 4] = 1'b1; // enable_vswitch_h 146 | assign ea_tech_cfg[i*18 + 5] = 1'b1; // enable_vddio 147 | assign ea_tech_cfg[i*18 + 6] = 1'b0; // ib_mode_sel 148 | assign ea_tech_cfg[i*18 + 7] = 1'b0; // vtrip_sel 149 | assign ea_tech_cfg[i*18 + 8] = 1'b0; // slow 150 | assign ea_tech_cfg[i*18 + 9] = 1'b0; // hld_ovr 151 | assign ea_tech_cfg[i*18 + 10] = 1'b0; // analog_en 152 | assign ea_tech_cfg[i*18 + 11] = 1'b0; // analog_sel 153 | assign ea_tech_cfg[i*18 + 12] = 1'b0; // analog_pol 154 | // strong pull-up, strong pull-down 155 | assign ea_tech_cfg[i*18 + 15:i*18 + 13] = 3'b110; // dm[2:0] 156 | end 157 | 158 | for(i=0;i<9;i=i+1) 159 | begin: so_tieoff 160 | wire tie_lo_esd, tie_hi_esd; 161 | assign tie_lo_esd = ea_tech_cfg[i*18 + 16]; 162 | assign tie_hi_esd = ea_tech_cfg[i*18 + 17]; 163 | 164 | assign so_tech_cfg[i*18 + 0] = 1'b1; // hld_h_n 165 | assign so_tech_cfg[i*18 + 1] = 1'b1; // enable_h 166 | assign so_tech_cfg[i*18 + 2] = tie_lo_esd; // enable_inp_h 167 | assign so_tech_cfg[i*18 + 3] = 1'b1; // enable_vdda_h 168 | assign so_tech_cfg[i*18 + 4] = 1'b1; // enable_vswitch_h 169 | assign so_tech_cfg[i*18 + 5] = 1'b1; // enable_vddio 170 | assign so_tech_cfg[i*18 + 6] = 1'b0; // ib_mode_sel 171 | assign so_tech_cfg[i*18 + 7] = 1'b0; // vtrip_sel 172 | assign so_tech_cfg[i*18 + 8] = 1'b0; // slow 173 | assign so_tech_cfg[i*18 + 9] = 1'b0; // hld_ovr 174 | assign so_tech_cfg[i*18 + 10] = 1'b0; // analog_en 175 | assign so_tech_cfg[i*18 + 11] = 1'b0; // analog_sel 176 | assign so_tech_cfg[i*18 + 12] = 1'b0; // analog_pol 177 | // strong pull-up, strong pull-down 178 | assign so_tech_cfg[i*18 + 15:i*18 + 13] = 3'b110; // dm[2:0] 179 | end 180 | endgenerate 181 | 182 | endmodule 183 | -------------------------------------------------------------------------------- /floorplan.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | GPIO = 'sky130_ef_io__gpiov2_pad_wrapped' 4 | VDD = 'sky130_ef_io__vccd_hvc_pad' 5 | VDDIO = 'sky130_ef_io__vddio_hvc_pad' 6 | VSS = 'sky130_ef_io__vssd_hvc_pad' 7 | VSSIO = 'sky130_ef_io__vssio_hvc_pad' 8 | CORNER = 'sky130_ef_io__corner_pad' 9 | FILL_CELLS = ['sky130_ef_io__com_bus_slice_1um', 10 | 'sky130_ef_io__com_bus_slice_5um', 11 | 'sky130_ef_io__com_bus_slice_10um', 12 | 'sky130_ef_io__com_bus_slice_20um'] 13 | 14 | 15 | def define_io_placement(): 16 | io = [GPIO] * 9 + [VSSIO, VDDIO, VDD, VSS] 17 | 18 | return io, io, io, io 19 | 20 | 21 | def generate_core_pins(chip): 22 | # Place pins 23 | pins = [ 24 | # (name, offset from cell edge, # bit in vector, width of vector) 25 | ('tech_cfg', 16, 18), # tie_lo_esd 26 | ('tech_cfg', 17, 18), # tie_hi_esd 27 | 28 | ('din', 0, 1), # in 29 | ('tech_cfg', 5, 18), # enable_vddio 30 | ('tech_cfg', 8, 18), # slow 31 | ('tech_cfg', 14, 18), # dm[1] 32 | ('tech_cfg', 10, 18), # analog_en 33 | ('tech_cfg', 13, 18), # dm[0] 34 | ('tech_cfg', 12, 18), # analog_pol 35 | ('ie', 0, 1), # inp_dis 36 | ('tech_cfg', 2, 18), # enable_inp_h 37 | ('tech_cfg', 1, 18), # enable_h 38 | ('tech_cfg', 0, 18), # hld_h_n 39 | ('tech_cfg', 11, 18), # analog_sel 40 | ('tech_cfg', 15, 18), # dm[2] 41 | ('tech_cfg', 9, 18), # hld_ovr 42 | ('dout', 0, 1), # out 43 | ('tech_cfg', 4, 18), # enable_vswitch_h 44 | ('tech_cfg', 3, 18), # enable_vdda_h 45 | ('tech_cfg', 7, 18), # vtrip_sel 46 | ('tech_cfg', 6, 18), # ib_mode_sel 47 | ('oen', 0, 1), # oe_n 48 | ] 49 | pins = list(reversed(pins)) 50 | 51 | we_pads, no_pads, ea_pads, so_pads = define_io_placement() 52 | 53 | # Filter out GPIO pins 54 | ea_pins = len(pins) * ea_pads.count(GPIO) 55 | for i in range(ea_pads.count(GPIO)): 56 | order_offset = len(pins) * i 57 | for pin_order, pin_spec in enumerate(pins): 58 | pin, bit, width = pin_spec 59 | # Construct name based on side, pin name, and bit # in vector 60 | name = f'we_{pin}[{i * width + bit}]' 61 | chip.set('constraint', 'pin', name, 'side', 1) 62 | chip.set('constraint', 'pin', name, 'order', ea_pins - (order_offset + pin_order)) 63 | 64 | # Repeat the same logic for each of the other 3 sides, with positions/axes 65 | # adjusted accordingly... 66 | no_pins = len(pins) * no_pads.count(GPIO) 67 | for i in range(no_pads.count(GPIO)): 68 | order_offset = len(pins) * i 69 | for pin_order, pin_spec in enumerate(pins): 70 | pin, bit, width = pin_spec 71 | # Construct name based on side, pin name, and bit # in vector 72 | name = f'no_{pin}[{i * width + bit}]' 73 | chip.set('constraint', 'pin', name, 'side', 2) 74 | chip.set('constraint', 'pin', name, 'order', no_pins - (order_offset + pin_order)) 75 | 76 | we_pins = len(pins) * we_pads.count(GPIO) 77 | for i in range(we_pads.count(GPIO)): 78 | order_offset = len(pins) * i 79 | for pin_order, pin_spec in enumerate(pins): 80 | pin, bit, width = pin_spec 81 | # Construct name based on side, pin name, and bit # in vector 82 | name = f'ea_{pin}[{i * width + bit}]' 83 | chip.set('constraint', 'pin', name, 'side', 3) 84 | chip.set('constraint', 'pin', name, 'order', we_pins - (order_offset + pin_order)) 85 | 86 | so_pins = len(pins) * so_pads.count(GPIO) 87 | for i in range(so_pads.count(GPIO)): 88 | order_offset = len(pins) * i 89 | for pin_order, pin_spec in enumerate(pins): 90 | pin, bit, width = pin_spec 91 | # Construct name based on side, pin name, and bit # in vector 92 | name = f'so_{pin}[{i * width + bit}]' 93 | chip.set('constraint', 'pin', name, 'side', 4) 94 | chip.set('constraint', 'pin', name, 'order', so_pins - (order_offset + pin_order)) 95 | 96 | 97 | def __configure_padring_side(chip, side_pads, side_name): 98 | pad_name_prefix = f'padring.i{side_name}.ipad' 99 | pad_name_suffix = '.i0.' 100 | 101 | pad_name_map = { 102 | GPIO: ('gbidir', 'gpio'), 103 | VDD: ('gvdd', 'iovdd'), 104 | VDDIO: ('gvddio', 'iovddio'), 105 | VSS: ('gvss', 'iovss'), 106 | VSSIO: ('gvssio', 'iovssio') 107 | } 108 | 109 | for i, pad_type in enumerate(side_pads): 110 | pad_type_name, pad_type_inst = pad_name_map[pad_type] 111 | pad_name = fr'{pad_name_prefix}\[{i}\]*.{pad_type_name}{pad_name_suffix}{pad_type_inst}' 112 | chip.add('tool', 'openroad', 'task', 'init_floorplan', 'var', f'padring_{side_name}_name', 113 | pad_name) 114 | 115 | 116 | def configure_padring(chip): 117 | # Place pads 118 | padring_file = os.path.join(os.path.dirname(__file__), 'openroad', 'padring.tcl') 119 | chip.set('tool', 'openroad', 'task', 'init_floorplan', 'file', 'padring', padring_file) 120 | 121 | we_pads, no_pads, ea_pads, so_pads = define_io_placement() 122 | 123 | __configure_padring_side(chip, we_pads, 'west') 124 | __configure_padring_side(chip, no_pads, 'north') 125 | __configure_padring_side(chip, ea_pads, 'east') 126 | __configure_padring_side(chip, so_pads, 'south') 127 | 128 | 129 | def generate_core_outline(chip): 130 | # Set up die area 131 | core_w = 1700 132 | core_h = 1200 133 | core_margin = 10 134 | diearea = [(0, 0), (core_w, core_h)] 135 | corearea = [(core_margin, core_margin), (core_w - core_margin, core_h - core_margin)] 136 | 137 | chip.set('constraint', 'outline', diearea) 138 | chip.set('constraint', 'corearea', corearea) 139 | 140 | 141 | def generate_core_floorplan(chip): 142 | generate_core_outline(chip) 143 | generate_core_pins(chip) 144 | 145 | # Global connections 146 | for gc in ('global_connect_core.tcl',): 147 | gc_path = os.path.join(os.path.dirname(__file__), 148 | 'openroad', 149 | gc) 150 | chip.add('tool', 'openroad', 'task', 'init_floorplan', 'file', 'global_connect', gc_path) 151 | 152 | # Define power grid 153 | for grid in ('pdngen_core_only.tcl', 'pdngen_sram.tcl'): 154 | pdngen_path = os.path.join(os.path.dirname(__file__), 155 | 'openroad', 156 | grid) 157 | chip.add('tool', 'openroad', 'task', 'power_grid', 'file', 'pdn_config', pdngen_path) 158 | 159 | 160 | def generate_top_outline(chip): 161 | # Create die area 162 | top_w = 2300 163 | top_h = 1800 164 | 165 | io_offset = 10 166 | core_offset = 220 167 | margin = core_offset + io_offset 168 | chip.set('constraint', 'outline', [(0, 0), (top_w, top_h)]) 169 | chip.set('constraint', 'corearea', [(margin, margin), (top_w - margin, top_h - margin)]) 170 | 171 | 172 | def generate_top_placement(chip): 173 | # Place core 174 | chip.set('constraint', 'component', 'core', 'placement', (300, 300)) 175 | 176 | 177 | def generate_top_floorplan(chip): 178 | generate_top_outline(chip) 179 | generate_top_placement(chip) 180 | configure_padring(chip) 181 | 182 | # Global connections 183 | for gc in ('global_connect_core_top.tcl', 'global_connect_io.tcl'): 184 | gc_file = os.path.join(os.path.dirname(__file__), 'openroad', gc) 185 | chip.add('tool', 'openroad', 'task', 'init_floorplan', 'file', 'global_connect', gc_file) 186 | 187 | # Define power grid 188 | for grid in ('pdngen_top.tcl', 'pdngen_core.tcl'): 189 | pdngen_file = os.path.join(os.path.dirname(__file__), 'openroad', grid) 190 | chip.add('tool', 'openroad', 'task', 'power_grid', 'file', 'pdn_config', pdngen_file) 191 | 192 | 193 | def generate_top_flat_floorplan(chip): 194 | generate_top_outline(chip) 195 | configure_padring(chip) 196 | 197 | # Global connections 198 | for gc in ('global_connect_core_top_flat.tcl', 'global_connect_io.tcl'): 199 | gc_file = os.path.join(os.path.dirname(__file__), 'openroad', gc) 200 | chip.add('tool', 'openroad', 'task', 'init_floorplan', 'file', 'global_connect', gc_file) 201 | 202 | # Define power grid 203 | for grid in ('pdngen_top.tcl', 'pdngen_sram.tcl'): 204 | pdngen_file = os.path.join(os.path.dirname(__file__), 'openroad', grid) 205 | chip.add('tool', 'openroad', 'task', 'power_grid', 'file', 'pdn_config', pdngen_file) 206 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | Copyright 2020 Zero ASIC Corporation 179 | 180 | Licensed under the Apache License, Version 2.0 (the "License"); 181 | you may not use this file except in compliance with the License. 182 | You may obtain a copy of the License at 183 | 184 | http://www.apache.org/licenses/LICENSE-2.0 185 | 186 | Unless required by applicable law or agreed to in writing, software 187 | distributed under the License is distributed on an "AS IS" BASIS, 188 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 189 | See the License for the specific language governing permissions and 190 | limitations under the License. 191 | -------------------------------------------------------------------------------- /hw/uart_core.sv: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | // 5 | // Description: UART core module 6 | // 7 | 8 | module uart_core ( 9 | input clk_i, 10 | input rst_ni, 11 | 12 | input uart_reg_pkg::uart_reg2hw_t reg2hw, 13 | output uart_reg_pkg::uart_hw2reg_t hw2reg, 14 | 15 | input rx, 16 | output logic tx, 17 | 18 | output logic intr_tx_watermark_o, 19 | output logic intr_rx_watermark_o, 20 | output logic intr_tx_empty_o, 21 | output logic intr_rx_overflow_o, 22 | output logic intr_rx_frame_err_o, 23 | output logic intr_rx_break_err_o, 24 | output logic intr_rx_timeout_o, 25 | output logic intr_rx_parity_err_o 26 | ); 27 | 28 | import uart_reg_pkg::*; 29 | 30 | localparam int NcoWidth = $bits(reg2hw.ctrl.nco.q); 31 | 32 | logic [15:0] rx_val_q; 33 | logic [7:0] uart_rdata; 34 | logic tick_baud_x16, rx_tick_baud; 35 | logic [5:0] tx_fifo_depth, rx_fifo_depth; 36 | logic [5:0] rx_fifo_depth_prev_q; 37 | logic [23:0] rx_timeout_count_d, rx_timeout_count_q, uart_rxto_val; 38 | logic rx_fifo_depth_changed, uart_rxto_en; 39 | logic tx_enable, rx_enable; 40 | logic sys_loopback, line_loopback, rxnf_enable; 41 | logic uart_fifo_rxrst, uart_fifo_txrst; 42 | logic [2:0] uart_fifo_rxilvl; 43 | logic [1:0] uart_fifo_txilvl; 44 | logic ovrd_tx_en, ovrd_tx_val; 45 | logic [7:0] tx_fifo_data; 46 | logic tx_fifo_rready, tx_fifo_rvalid; 47 | logic tx_fifo_wready, tx_uart_idle; 48 | logic tx_out; 49 | logic tx_out_q; 50 | logic [7:0] rx_fifo_data; 51 | logic rx_valid, rx_fifo_wvalid, rx_fifo_rvalid; 52 | logic rx_fifo_wready, rx_uart_idle; 53 | logic rx_sync; 54 | logic rx_in; 55 | logic break_err; 56 | logic [4:0] allzero_cnt_d, allzero_cnt_q; 57 | logic allzero_err, not_allzero_char; 58 | logic event_tx_watermark, event_rx_watermark, event_tx_empty, event_rx_overflow; 59 | logic event_rx_frame_err, event_rx_break_err, event_rx_timeout, event_rx_parity_err; 60 | logic tx_watermark_d, tx_watermark_prev_q; 61 | logic rx_watermark_d, rx_watermark_prev_q; 62 | logic tx_uart_idle_q; 63 | 64 | assign tx_enable = reg2hw.ctrl.tx.q; 65 | assign rx_enable = reg2hw.ctrl.rx.q; 66 | assign rxnf_enable = reg2hw.ctrl.nf.q; 67 | assign sys_loopback = reg2hw.ctrl.slpbk.q; 68 | assign line_loopback = reg2hw.ctrl.llpbk.q; 69 | 70 | assign uart_fifo_rxrst = reg2hw.fifo_ctrl.rxrst.q & reg2hw.fifo_ctrl.rxrst.qe; 71 | assign uart_fifo_txrst = reg2hw.fifo_ctrl.txrst.q & reg2hw.fifo_ctrl.txrst.qe; 72 | assign uart_fifo_rxilvl = reg2hw.fifo_ctrl.rxilvl.q; 73 | assign uart_fifo_txilvl = reg2hw.fifo_ctrl.txilvl.q; 74 | 75 | assign ovrd_tx_en = reg2hw.ovrd.txen.q; 76 | assign ovrd_tx_val = reg2hw.ovrd.txval.q; 77 | 78 | typedef enum logic { 79 | BRK_CHK, 80 | BRK_WAIT 81 | } break_st_e ; 82 | 83 | break_st_e break_st_q; 84 | 85 | assign not_allzero_char = rx_valid & (~event_rx_frame_err | (rx_fifo_data != 8'h0)); 86 | assign allzero_err = event_rx_frame_err & (rx_fifo_data == 8'h0); 87 | 88 | 89 | assign allzero_cnt_d = (break_st_q == BRK_WAIT || not_allzero_char) ? 5'h0 : 90 | //allzero_cnt_q[4] never be 1b without break_st_q as BRK_WAIT 91 | //allzero_cnt_q[4] ? allzero_cnt_q : 92 | allzero_err ? allzero_cnt_q + 5'd1 : 93 | allzero_cnt_q; 94 | 95 | always_ff @(posedge clk_i or negedge rst_ni) begin 96 | if (!rst_ni) allzero_cnt_q <= '0; 97 | else if (rx_enable) allzero_cnt_q <= allzero_cnt_d; 98 | end 99 | 100 | // break_err edges in same cycle as event_rx_frame_err edges ; that way the 101 | // reset-on-read works the same way for break and frame error interrupts. 102 | 103 | always_comb begin 104 | unique case (reg2hw.ctrl.rxblvl.q) 105 | 2'h0: break_err = allzero_cnt_d >= 5'd2; 106 | 2'h1: break_err = allzero_cnt_d >= 5'd4; 107 | 2'h2: break_err = allzero_cnt_d >= 5'd8; 108 | default: break_err = allzero_cnt_d >= 5'd16; 109 | endcase 110 | end 111 | 112 | always_ff @(posedge clk_i or negedge rst_ni) begin 113 | if (!rst_ni) break_st_q <= BRK_CHK; 114 | else begin 115 | unique case (break_st_q) 116 | BRK_CHK: begin 117 | if (event_rx_break_err) break_st_q <= BRK_WAIT; 118 | end 119 | 120 | BRK_WAIT: begin 121 | if (rx_in) break_st_q <= BRK_CHK; 122 | end 123 | 124 | default: begin 125 | break_st_q <= BRK_CHK; 126 | end 127 | endcase 128 | end 129 | end 130 | 131 | assign hw2reg.val.d = rx_val_q; 132 | 133 | assign hw2reg.rdata.d = uart_rdata; 134 | 135 | assign hw2reg.status.rxempty.d = ~rx_fifo_rvalid; 136 | assign hw2reg.status.rxidle.d = rx_uart_idle; 137 | assign hw2reg.status.txidle.d = tx_uart_idle & ~tx_fifo_rvalid; 138 | assign hw2reg.status.txempty.d = ~tx_fifo_rvalid; 139 | assign hw2reg.status.rxfull.d = ~rx_fifo_wready; 140 | assign hw2reg.status.txfull.d = ~tx_fifo_wready; 141 | 142 | assign hw2reg.fifo_status.txlvl.d = tx_fifo_depth; 143 | assign hw2reg.fifo_status.rxlvl.d = rx_fifo_depth; 144 | 145 | // resets are self-clearing, so need to update FIFO_CTRL 146 | assign hw2reg.fifo_ctrl.rxilvl.de = 1'b0; 147 | assign hw2reg.fifo_ctrl.rxilvl.d = 3'h0; 148 | assign hw2reg.fifo_ctrl.txilvl.de = 1'b0; 149 | assign hw2reg.fifo_ctrl.txilvl.d = 2'h0; 150 | 151 | // NCO 16x Baud Generator 152 | // output clock rate is: 153 | // Fin * (NCO/2**NcoWidth) 154 | logic [NcoWidth:0] nco_sum_q; // extra bit to get the carry 155 | 156 | always_ff @(posedge clk_i or negedge rst_ni) begin 157 | if (!rst_ni) begin 158 | nco_sum_q <= 17'h0; 159 | end else if (tx_enable || rx_enable) begin 160 | nco_sum_q <= {1'b0,nco_sum_q[NcoWidth-1:0]} + {1'b0,reg2hw.ctrl.nco.q[NcoWidth-1:0]}; 161 | end 162 | end 163 | 164 | assign tick_baud_x16 = nco_sum_q[16]; 165 | 166 | ////////////// 167 | // TX Logic // 168 | ////////////// 169 | 170 | assign tx_fifo_rready = tx_uart_idle & tx_fifo_rvalid & tx_enable; 171 | 172 | prim_fifo_sync #( 173 | .Width (8), 174 | .Pass (1'b0), 175 | .Depth (4) 176 | ) u_uart_txfifo ( 177 | .clk_i, 178 | .rst_ni, 179 | .clr_i (uart_fifo_txrst), 180 | .wvalid_i(reg2hw.wdata.qe), 181 | .wready_o(tx_fifo_wready), 182 | .wdata_i (reg2hw.wdata.q), 183 | .depth_o (tx_fifo_depth), 184 | .full_o (), 185 | .rvalid_o(tx_fifo_rvalid), 186 | .rready_i(tx_fifo_rready), 187 | .rdata_o (tx_fifo_data) 188 | ); 189 | 190 | uart_tx uart_tx ( 191 | .clk_i, 192 | .rst_ni, 193 | .tx_enable, 194 | .tick_baud_x16, 195 | .parity_enable (reg2hw.ctrl.parity_en.q), 196 | .wr (tx_fifo_rready), 197 | .wr_parity ((^tx_fifo_data) ^ reg2hw.ctrl.parity_odd.q), 198 | .wr_data (tx_fifo_data), 199 | .idle (tx_uart_idle), 200 | .tx (tx_out) 201 | ); 202 | 203 | assign tx = line_loopback ? rx : tx_out_q ; 204 | always_ff @(posedge clk_i or negedge rst_ni) begin 205 | if (!rst_ni) begin 206 | tx_out_q <= 1'b1; 207 | end else if (ovrd_tx_en) begin 208 | tx_out_q <= ovrd_tx_val ; 209 | end else if (sys_loopback) begin 210 | tx_out_q <= 1'b1; 211 | end else begin 212 | tx_out_q <= tx_out; 213 | end 214 | end 215 | 216 | ////////////// 217 | // RX Logic // 218 | ////////////// 219 | 220 | // sync the incoming data 221 | prim_flop_2sync #( 222 | .Width(1), 223 | .ResetValue(1'b1) 224 | ) sync_rx ( 225 | .clk_i, 226 | .rst_ni, 227 | .d_i(rx), 228 | .q_o(rx_sync) 229 | ); 230 | 231 | // Based on: en.wikipedia.org/wiki/Repetition_code mentions the use of a majority filter 232 | // in UART to ignore brief noise spikes 233 | logic rx_sync_q1, rx_sync_q2, rx_in_mx, rx_in_maj; 234 | 235 | always_ff @(posedge clk_i or negedge rst_ni) begin 236 | if (!rst_ni) begin 237 | rx_sync_q1 <= 1'b1; 238 | rx_sync_q2 <= 1'b1; 239 | end else begin 240 | rx_sync_q1 <= rx_sync; 241 | rx_sync_q2 <= rx_sync_q1; 242 | end 243 | end 244 | 245 | assign rx_in_maj = (rx_sync & rx_sync_q1) | 246 | (rx_sync & rx_sync_q2) | 247 | (rx_sync_q1 & rx_sync_q2); 248 | assign rx_in_mx = rxnf_enable ? rx_in_maj : rx_sync; 249 | 250 | assign rx_in = sys_loopback ? tx_out : 251 | line_loopback ? 1'b1 : 252 | rx_in_mx; 253 | 254 | uart_rx uart_rx ( 255 | .clk_i, 256 | .rst_ni, 257 | .rx_enable, 258 | .tick_baud_x16, 259 | .parity_enable (reg2hw.ctrl.parity_en.q), 260 | .parity_odd (reg2hw.ctrl.parity_odd.q), 261 | .tick_baud (rx_tick_baud), 262 | .rx_valid, 263 | .rx_data (rx_fifo_data), 264 | .idle (rx_uart_idle), 265 | .frame_err (event_rx_frame_err), 266 | .rx (rx_in), 267 | .rx_parity_err (event_rx_parity_err) 268 | ); 269 | 270 | assign rx_fifo_wvalid = rx_valid & ~event_rx_frame_err & ~event_rx_parity_err; 271 | 272 | prim_fifo_sync #( 273 | .Width (8), 274 | .Pass (1'b0), 275 | .Depth (4) 276 | ) u_uart_rxfifo ( 277 | .clk_i, 278 | .rst_ni, 279 | .clr_i (uart_fifo_rxrst), 280 | .wvalid_i(rx_fifo_wvalid), 281 | .wready_o(rx_fifo_wready), 282 | .wdata_i (rx_fifo_data), 283 | .depth_o (rx_fifo_depth), 284 | .full_o (), 285 | .rvalid_o(rx_fifo_rvalid), 286 | .rready_i(reg2hw.rdata.re), 287 | .rdata_o (uart_rdata) 288 | ); 289 | 290 | always_ff @(posedge clk_i or negedge rst_ni) begin 291 | if (!rst_ni) rx_val_q <= 16'h0; 292 | else if (tick_baud_x16) rx_val_q <= {rx_val_q[14:0], rx_in}; 293 | end 294 | 295 | //////////////////////// 296 | // Interrupt & Status // 297 | //////////////////////// 298 | 299 | always_comb begin 300 | unique case(uart_fifo_txilvl) 301 | 2'h0: tx_watermark_d = (tx_fifo_depth < 6'd2); 302 | 2'h1: tx_watermark_d = (tx_fifo_depth < 6'd4); 303 | 2'h2: tx_watermark_d = (tx_fifo_depth < 6'd8); 304 | default: tx_watermark_d = (tx_fifo_depth < 6'd16); 305 | endcase 306 | end 307 | 308 | assign event_tx_watermark = tx_watermark_d & ~tx_watermark_prev_q; 309 | 310 | // The empty condition handling is a bit different. 311 | // If empty rising conditions were detected directly, then every first write of a burst 312 | // would trigger an empty. This is due to the fact that the uart_tx fsm immediately 313 | // withdraws the content and asserts "empty". 314 | // To guard against this false trigger, empty is qualified with idle to extend the window 315 | // in which software has an opportunity to deposit new data. 316 | // However, if software deposit speed is TOO slow, this would still be an issue. 317 | // 318 | // The alternative software fix is to disable tx_enable until it has a chance to 319 | // burst in the desired amount of data. 320 | assign event_tx_empty = ~tx_fifo_rvalid & ~tx_uart_idle_q & tx_uart_idle; 321 | 322 | always_ff @(posedge clk_i or negedge rst_ni) begin 323 | if (!rst_ni) begin 324 | tx_watermark_prev_q <= 1'b1; // by default watermark condition is true 325 | rx_watermark_prev_q <= 1'b0; // by default watermark condition is false 326 | tx_uart_idle_q <= 1'b1; 327 | end else begin 328 | tx_watermark_prev_q <= tx_watermark_d; 329 | rx_watermark_prev_q <= rx_watermark_d; 330 | tx_uart_idle_q <= tx_uart_idle; 331 | end 332 | end 333 | 334 | always_comb begin 335 | unique case(uart_fifo_rxilvl) 336 | 3'h0: rx_watermark_d = (rx_fifo_depth >= 6'd1); 337 | 3'h1: rx_watermark_d = (rx_fifo_depth >= 6'd4); 338 | 3'h2: rx_watermark_d = (rx_fifo_depth >= 6'd8); 339 | 3'h3: rx_watermark_d = (rx_fifo_depth >= 6'd16); 340 | 3'h4: rx_watermark_d = (rx_fifo_depth >= 6'd30); 341 | default: rx_watermark_d = 1'b0; 342 | endcase 343 | end 344 | 345 | assign event_rx_watermark = rx_watermark_d & ~rx_watermark_prev_q; 346 | 347 | // rx timeout interrupt 348 | assign uart_rxto_en = reg2hw.timeout_ctrl.en.q; 349 | assign uart_rxto_val = reg2hw.timeout_ctrl.val.q; 350 | 351 | assign rx_fifo_depth_changed = (rx_fifo_depth != rx_fifo_depth_prev_q); 352 | 353 | assign rx_timeout_count_d = 354 | // don't count if timeout feature not enabled ; 355 | // will never reach timeout val + lower power 356 | (uart_rxto_en == 1'b0) ? 24'd0 : 357 | // reset count if timeout interrupt is set 358 | event_rx_timeout ? 24'd0 : 359 | // reset count upon change in fifo level: covers both read and receiving a new byte 360 | rx_fifo_depth_changed ? 24'd0 : 361 | // reset count if no bytes are pending 362 | (rx_fifo_depth == '0) ? 24'd0 : 363 | // stop the count at timeout value (this will set the interrupt) 364 | // Removed below line as when the timeout reaches the value, 365 | // event occured, and timeout value reset to 0h. 366 | //(rx_timeout_count_q == uart_rxto_val) ? rx_timeout_count_q : 367 | // increment if at rx baud tick 368 | rx_tick_baud ? (rx_timeout_count_q + 24'd1) : 369 | rx_timeout_count_q; 370 | 371 | assign event_rx_timeout = (rx_timeout_count_q == uart_rxto_val) & uart_rxto_en; 372 | 373 | always_ff @(posedge clk_i or negedge rst_ni) begin 374 | if (!rst_ni) begin 375 | rx_timeout_count_q <= 24'd0; 376 | rx_fifo_depth_prev_q <= 6'd0; 377 | end else begin 378 | rx_timeout_count_q <= rx_timeout_count_d; 379 | rx_fifo_depth_prev_q <= rx_fifo_depth; 380 | end 381 | end 382 | 383 | assign event_rx_overflow = rx_fifo_wvalid & ~rx_fifo_wready; 384 | assign event_rx_break_err = break_err & (break_st_q == BRK_CHK); 385 | 386 | // instantiate interrupt hardware primitives 387 | 388 | prim_intr_hw #(.Width(1)) intr_hw_tx_watermark ( 389 | .clk_i, 390 | .rst_ni, 391 | .event_intr_i (event_tx_watermark), 392 | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.tx_watermark.q), 393 | .reg2hw_intr_test_q_i (reg2hw.intr_test.tx_watermark.q), 394 | .reg2hw_intr_test_qe_i (reg2hw.intr_test.tx_watermark.qe), 395 | .reg2hw_intr_state_q_i (reg2hw.intr_state.tx_watermark.q), 396 | .hw2reg_intr_state_de_o (hw2reg.intr_state.tx_watermark.de), 397 | .hw2reg_intr_state_d_o (hw2reg.intr_state.tx_watermark.d), 398 | .intr_o (intr_tx_watermark_o) 399 | ); 400 | 401 | prim_intr_hw #(.Width(1)) intr_hw_rx_watermark ( 402 | .clk_i, 403 | .rst_ni, 404 | .event_intr_i (event_rx_watermark), 405 | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rx_watermark.q), 406 | .reg2hw_intr_test_q_i (reg2hw.intr_test.rx_watermark.q), 407 | .reg2hw_intr_test_qe_i (reg2hw.intr_test.rx_watermark.qe), 408 | .reg2hw_intr_state_q_i (reg2hw.intr_state.rx_watermark.q), 409 | .hw2reg_intr_state_de_o (hw2reg.intr_state.rx_watermark.de), 410 | .hw2reg_intr_state_d_o (hw2reg.intr_state.rx_watermark.d), 411 | .intr_o (intr_rx_watermark_o) 412 | ); 413 | 414 | prim_intr_hw #(.Width(1)) intr_hw_tx_empty ( 415 | .clk_i, 416 | .rst_ni, 417 | .event_intr_i (event_tx_empty), 418 | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.tx_empty.q), 419 | .reg2hw_intr_test_q_i (reg2hw.intr_test.tx_empty.q), 420 | .reg2hw_intr_test_qe_i (reg2hw.intr_test.tx_empty.qe), 421 | .reg2hw_intr_state_q_i (reg2hw.intr_state.tx_empty.q), 422 | .hw2reg_intr_state_de_o (hw2reg.intr_state.tx_empty.de), 423 | .hw2reg_intr_state_d_o (hw2reg.intr_state.tx_empty.d), 424 | .intr_o (intr_tx_empty_o) 425 | ); 426 | 427 | prim_intr_hw #(.Width(1)) intr_hw_rx_overflow ( 428 | .clk_i, 429 | .rst_ni, 430 | .event_intr_i (event_rx_overflow), 431 | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rx_overflow.q), 432 | .reg2hw_intr_test_q_i (reg2hw.intr_test.rx_overflow.q), 433 | .reg2hw_intr_test_qe_i (reg2hw.intr_test.rx_overflow.qe), 434 | .reg2hw_intr_state_q_i (reg2hw.intr_state.rx_overflow.q), 435 | .hw2reg_intr_state_de_o (hw2reg.intr_state.rx_overflow.de), 436 | .hw2reg_intr_state_d_o (hw2reg.intr_state.rx_overflow.d), 437 | .intr_o (intr_rx_overflow_o) 438 | ); 439 | 440 | prim_intr_hw #(.Width(1)) intr_hw_rx_frame_err ( 441 | .clk_i, 442 | .rst_ni, 443 | .event_intr_i (event_rx_frame_err), 444 | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rx_frame_err.q), 445 | .reg2hw_intr_test_q_i (reg2hw.intr_test.rx_frame_err.q), 446 | .reg2hw_intr_test_qe_i (reg2hw.intr_test.rx_frame_err.qe), 447 | .reg2hw_intr_state_q_i (reg2hw.intr_state.rx_frame_err.q), 448 | .hw2reg_intr_state_de_o (hw2reg.intr_state.rx_frame_err.de), 449 | .hw2reg_intr_state_d_o (hw2reg.intr_state.rx_frame_err.d), 450 | .intr_o (intr_rx_frame_err_o) 451 | ); 452 | 453 | prim_intr_hw #(.Width(1)) intr_hw_rx_break_err ( 454 | .clk_i, 455 | .rst_ni, 456 | .event_intr_i (event_rx_break_err), 457 | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rx_break_err.q), 458 | .reg2hw_intr_test_q_i (reg2hw.intr_test.rx_break_err.q), 459 | .reg2hw_intr_test_qe_i (reg2hw.intr_test.rx_break_err.qe), 460 | .reg2hw_intr_state_q_i (reg2hw.intr_state.rx_break_err.q), 461 | .hw2reg_intr_state_de_o (hw2reg.intr_state.rx_break_err.de), 462 | .hw2reg_intr_state_d_o (hw2reg.intr_state.rx_break_err.d), 463 | .intr_o (intr_rx_break_err_o) 464 | ); 465 | 466 | prim_intr_hw #(.Width(1)) intr_hw_rx_timeout ( 467 | .clk_i, 468 | .rst_ni, 469 | .event_intr_i (event_rx_timeout), 470 | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rx_timeout.q), 471 | .reg2hw_intr_test_q_i (reg2hw.intr_test.rx_timeout.q), 472 | .reg2hw_intr_test_qe_i (reg2hw.intr_test.rx_timeout.qe), 473 | .reg2hw_intr_state_q_i (reg2hw.intr_state.rx_timeout.q), 474 | .hw2reg_intr_state_de_o (hw2reg.intr_state.rx_timeout.de), 475 | .hw2reg_intr_state_d_o (hw2reg.intr_state.rx_timeout.d), 476 | .intr_o (intr_rx_timeout_o) 477 | ); 478 | 479 | prim_intr_hw #(.Width(1)) intr_hw_rx_parity_err ( 480 | .clk_i, 481 | .rst_ni, 482 | .event_intr_i (event_rx_parity_err), 483 | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rx_parity_err.q), 484 | .reg2hw_intr_test_q_i (reg2hw.intr_test.rx_parity_err.q), 485 | .reg2hw_intr_test_qe_i (reg2hw.intr_test.rx_parity_err.qe), 486 | .reg2hw_intr_state_q_i (reg2hw.intr_state.rx_parity_err.q), 487 | .hw2reg_intr_state_de_o (hw2reg.intr_state.rx_parity_err.de), 488 | .hw2reg_intr_state_d_o (hw2reg.intr_state.rx_parity_err.d), 489 | .intr_o (intr_rx_parity_err_o) 490 | ); 491 | 492 | endmodule 493 | -------------------------------------------------------------------------------- /make.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | ZeroSOC build system 4 | ''' 5 | 6 | from siliconcompiler import Design, ASIC 7 | from siliconcompiler.tools import get_task 8 | from lambdalib.ramlib import Spram 9 | from lambdalib.padring import Padring 10 | 11 | import argparse 12 | import os 13 | import sys 14 | 15 | # # Libraries 16 | # from lambdapdk.sky130.libs import sky130sram, sky130io 17 | from siliconcompiler.targets import skywater130_demo 18 | 19 | # from siliconcompiler.tools.openroad import openroad 20 | # from siliconcompiler.tools._common import get_tool_tasks as _get_tool_tasks 21 | 22 | # import floorplan as zerosoc_floorplan 23 | # import zerosoc_core 24 | # import zerosoc_top 25 | 26 | ASIC_CORE_CFG = 'zerosoc_core.pkg.json' 27 | 28 | 29 | from siliconcompiler.flows.asicflow import SV2VASICFlow 30 | from siliconcompiler.tools.openroad.init_floorplan import InitFloorplanTask 31 | from siliconcompiler.tools.openroad._apr import OpenROADPSMParameter 32 | from siliconcompiler.tools.openroad._apr import APRTask 33 | from siliconcompiler.tools.openroad.power_grid import PowerGridTask 34 | 35 | 36 | 37 | class OpenTITAN(Design): 38 | def __init__(self): 39 | super().__init__("opentitan") 40 | 41 | self.set_dataroot("opentitan", 42 | 'git+https://github.com/lowRISC/opentitan.git', 43 | tag='8b9fe4bf2db8ccfac0b26600decf07cf41867e07') 44 | 45 | with self.active_dataroot("opentitan"), self.active_fileset("rtl"): 46 | self.add_idir("hw/ip/prim/rtl") 47 | self.add_idir("hw/dv/sv/dv_utils") 48 | 49 | # SV packages (need to be added explicitly) 50 | self.add_file('hw/top_earlgrey/rtl/top_pkg.sv') 51 | 52 | self.add_file('hw/ip/gpio/rtl/gpio_reg_pkg.sv') 53 | self.add_file('hw/ip/gpio/rtl/gpio_reg_top.sv') 54 | self.add_file('hw/ip/gpio/rtl/gpio.sv') 55 | 56 | self.add_file('hw/ip/uart/rtl/uart_reg_pkg.sv') 57 | self.add_file('hw/ip/uart/rtl/uart_reg_top.sv') 58 | self.add_file('hw/ip/uart/rtl/uart_rx.sv') 59 | self.add_file('hw/ip/uart/rtl/uart_tx.sv') 60 | self.add_file('hw/ip/uart/rtl/uart.sv') 61 | 62 | self.add_file('hw/ip/prim/rtl/prim_alert_pkg.sv') 63 | self.add_file('hw/ip/prim/rtl/prim_secded_pkg.sv') 64 | self.add_file('hw/ip/prim/rtl/prim_esc_pkg.sv') 65 | self.add_file('hw/ip/prim/rtl/prim_otp_pkg.sv') 66 | self.add_file('hw/ip/prim/rtl/prim_pad_wrapper_pkg.sv') 67 | self.add_file('hw/ip/prim/rtl/prim_ram_1p_pkg.sv') 68 | self.add_file('hw/ip/prim/rtl/prim_ram_2p_pkg.sv') 69 | self.add_file('hw/ip/prim/rtl/prim_rom_pkg.sv') 70 | self.add_file('hw/ip/prim/rtl/prim_subreg_arb.sv') 71 | self.add_file('hw/ip/prim/rtl/prim_subreg.sv') 72 | self.add_file('hw/ip/prim/rtl/prim_subreg_ext.sv') 73 | self.add_file('hw/ip/prim/rtl/prim_subreg_shadow.sv') 74 | self.add_file('hw/ip/prim/rtl/prim_intr_hw.sv') 75 | self.add_file('hw/ip/prim/rtl/prim_fifo_sync.sv') 76 | self.add_file('hw/ip/prim/rtl/prim_filter_ctr.sv') 77 | self.add_file('hw/ip/prim/rtl/prim_ram_1p_adv.sv') 78 | self.add_file('hw/ip/prim/rtl/prim_secded_64_57_dec.sv') 79 | self.add_file('hw/ip/prim/rtl/prim_secded_64_57_enc.sv') 80 | self.add_file('hw/ip/prim/rtl/prim_arbiter_ppc.sv') 81 | self.add_file('hw/ip/prim/rtl/prim_lc_sync.sv') 82 | self.add_file('hw/ip/prim/rtl/prim_esc_receiver.sv') 83 | self.add_file('hw/ip/prim/rtl/prim_diff_decode.sv') 84 | 85 | self.add_file('hw/ip/prim_generic/rtl/prim_generic_flop_2sync.sv') 86 | self.add_file('hw/ip/prim_generic/rtl/prim_generic_flop.sv') 87 | self.add_file('hw/ip/prim_generic/rtl/prim_generic_buf.sv') 88 | 89 | self.add_file('hw/ip/tlul/rtl/tlul_pkg.sv') 90 | self.add_file('hw/ip/tlul/rtl/tlul_adapter_sram.sv') 91 | self.add_file('hw/ip/tlul/rtl/tlul_socket_1n.sv') 92 | self.add_file('hw/ip/tlul/rtl/tlul_socket_m1.sv') 93 | self.add_file('hw/ip/tlul/rtl/tlul_cmd_intg_chk.sv') 94 | self.add_file('hw/ip/tlul/rtl/tlul_rsp_intg_gen.sv') 95 | self.add_file('hw/ip/tlul/rtl/tlul_adapter_reg.sv') 96 | self.add_file('hw/ip/tlul/rtl/tlul_fifo_sync.sv') 97 | self.add_file('hw/ip/tlul/rtl/tlul_err.sv') 98 | self.add_file('hw/ip/tlul/rtl/tlul_err_resp.sv') 99 | self.add_file('hw/ip/tlul/rtl/tlul_adapter_host.sv') 100 | self.add_file('hw/ip/tlul/rtl/tlul_cmd_intg_gen.sv') 101 | self.add_file('hw/ip/tlul/rtl/tlul_rsp_intg_chk.sv') 102 | 103 | self.add_file('hw/ip/prim/rtl/prim_util_pkg.sv') 104 | self.add_file('hw/ip/prim/rtl/prim_secded_pkg.sv') 105 | 106 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_pkg.sv') 107 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_top.sv') 108 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_core.sv') 109 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv') 110 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv') 111 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv') 112 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv') 113 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv') 114 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv') 115 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv') 116 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_prefetch_buffer.sv') 117 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_fetch_fifo.sv') 118 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_csr.sv') 119 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_counter.sv') 120 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv') 121 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv') 122 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_alu.sv') 123 | 124 | self.add_file('hw/ip/lc_ctrl/rtl/lc_ctrl_state_pkg.sv') 125 | self.add_file('hw/ip/lc_ctrl/rtl/lc_ctrl_pkg.sv') 126 | 127 | self.add_file("hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv") 128 | 129 | # Hack to work around Yosys + Surelog issue. Even though this is found in 130 | # one of our ydirs, we get different synthesis results if this isn't ordered 131 | # earlier. 132 | self.add_file('hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv') 133 | 134 | 135 | class ZeroSOC(Design): 136 | def __init__(self): 137 | super().__init__("zerosoc") 138 | 139 | self.set_dataroot("zerosoc", __file__) 140 | 141 | with self.active_dataroot("zerosoc"), self.active_fileset("rtl.core"): 142 | self.set_topmodule("asic_core") 143 | self.add_idir("hw") 144 | self.add_file("hw/xbar_pkg.sv") 145 | self.add_file("hw/prim/prim_pkg.sv") 146 | self.add_file("hw/uart_core.sv") 147 | self.add_file("hw/zerosoc.sv") 148 | self.add_file("hw/xbar.sv") 149 | self.add_file("hw/tl_dbg.sv") 150 | self.add_file("hw/asic_core.v") 151 | self.add_file("hw/xbar.sv") 152 | self.add_file("hw/xbar.sv") 153 | self.add_file('hw/prim/lambdalib/prim_lambdalib_ram_1p.v') 154 | self.add_file('hw/prim/lambdalib/prim_lambdalib_clock_gating.v') 155 | self.add_file('hw/prim/prim_flop_2sync.sv') 156 | self.add_file('hw/prim/prim_ram_1p.sv') 157 | self.add_file('hw/prim/prim_flop.sv') 158 | self.add_file('hw/prim/prim_clock_gating.sv') 159 | self.add_file('hw/prim/prim_buf.sv') 160 | 161 | self.add_define('PRIM_DEFAULT_IMPL=prim_pkg::ImplLambdalib') 162 | self.add_define('RAM_DEPTH=512') 163 | self.add_define(f'MEM_ROOT={self.get_dataroot("zerosoc")}') 164 | self.add_define('SYNTHESIS') 165 | 166 | self.add_depfileset(Spram(), "rtl") 167 | self.add_depfileset(OpenTITAN(), "rtl") 168 | 169 | with self.active_dataroot("zerosoc"), self.active_fileset("rtl.top"): 170 | self.set_topmodule("asic_top") 171 | self.add_file("hw/asic_top.v") 172 | self.add_depfileset(self, "rtl.core") 173 | self.add_depfileset(Padring(), "rtl") 174 | 175 | with self.active_dataroot("zerosoc"), self.active_fileset("padring.sky130"): 176 | self.add_file("openroad/padring.tcl") 177 | 178 | with self.active_dataroot("zerosoc"), self.active_fileset("globalconns.flattop"): 179 | self.add_file("openroad/global_connect_core_top_flat.tcl") 180 | self.add_file("openroad/global_connect_io.tcl") 181 | 182 | with self.active_dataroot("zerosoc"), self.active_fileset("pdn.flattop"): 183 | self.add_file("openroad/pdngen_top.tcl") 184 | self.add_file("openroad/pdngen_sram.tcl") 185 | 186 | with self.active_dataroot("zerosoc"), self.active_fileset("sdc.top.sky130"): 187 | self.add_file("hw/asic_top.sdc") 188 | 189 | 190 | def build_fpga(): 191 | chip = siliconcompiler.Chip('top_icebreaker') 192 | 193 | chip.set('fpga', 'partname', 'ice40up5k-sg48') 194 | chip.use(fpgaflow_demo, partname='ice40up5k-sg48') 195 | 196 | chip.use(zerosoc_core) 197 | 198 | chip.input('hw/top_icebreaker.v', package='zerosoc') 199 | chip.input('hw/prim/ice40/prim_ice40_clock_gating.v', package='zerosoc') 200 | chip.input('fpga/icebreaker.pcf', package='zerosoc') 201 | 202 | chip.add('option', 'define', 'PRIM_DEFAULT_IMPL="prim_pkg::ImplIce40"') 203 | 204 | _run_build(chip) 205 | 206 | 207 | def _setup_core(): 208 | chip = siliconcompiler.Chip('zerosoc_core') 209 | chip.set('option', 'entrypoint', 'asic_core') 210 | 211 | chip.use(skywater130_demo) 212 | 213 | chip.add('option', 'define', 'SYNTHESIS') 214 | chip.use(zerosoc_core) 215 | 216 | chip.use(sky130sram) 217 | chip.swap_library('lambdalib_ramlib', 'lambdalib_sky130sram') 218 | 219 | # Ignore cells in these libraries during DRC, they violate the rules but are 220 | # foundry-validated 221 | for task in ('extspice', 'drc'): 222 | chip.add('tool', 'magic', 'task', task, 'var', 'exclude', 'sky130_sram_1rw1r_64x256_8') 223 | chip.add('tool', 'netgen', 'task', 'lvs', 'var', 'exclude', 'sky130_sram_1rw1r_64x256_8') 224 | 225 | chip.set('tool', 'openroad', 'task', 'write_data', 'var', 226 | 'ord_abstract_lef_bloat_layers', False) 227 | 228 | chip.clock(r'we_din\[5\]', period=66) 229 | 230 | chip.set('tool', 'openroad', 'task', 'macro_placement', 'var', 'rtlmp_enable', 'true') 231 | chip.set('tool', 'openroad', 'task', 'write_data', 'var', 'write_cdl', 'false') 232 | chip.set('option', 'var', 'openroad_place_density', '0.40') 233 | chip.set('option', 'var', 'openroad_grt_macro_extension', '0') 234 | 235 | zerosoc_floorplan.generate_core_floorplan(chip) 236 | 237 | return chip 238 | 239 | 240 | def _setup_core_module(chip): 241 | # set up pointers to final outputs for integration 242 | # Set physical outputs 243 | stackup = chip.get('option', 'stackup') 244 | chip.set('output', stackup, 'gds', chip.find_result('gds', step='write.gds')) 245 | chip.set('output', stackup, 'lef', chip.find_result('lef', step='write.views')) 246 | 247 | # Set output netlist 248 | chip.set('output', 'netlist', 'verilog', chip.find_result('vg', step='write.views')) 249 | 250 | # Set timing libraries 251 | for scenario in chip.getkeys('constraint', 'timing'): 252 | corner = chip.get('constraint', 'timing', scenario, 'libcorner')[0] 253 | lib = chip.find_result(f'{corner}.lib', step='write.views') 254 | chip.set('output', corner, 'nldm', lib) 255 | 256 | # Set pex outputs 257 | for scenario in chip.getkeys('constraint', 'timing'): 258 | corner = chip.get('constraint', 'timing', scenario, 'pexcorner') 259 | spef = chip.find_result(f'{corner}.spef', step='write.views') 260 | chip.set('output', corner, 'spef', spef) 261 | 262 | # Hash output files 263 | for fileset in chip.getkeys('output'): 264 | for filetype in chip.getkeys('output', fileset): 265 | chip.hash_files('output', fileset, filetype) 266 | 267 | chip.write_manifest(ASIC_CORE_CFG) 268 | 269 | 270 | def build_core(verify=True, remote=False, resume=False, floorplan=False): 271 | chip = _setup_core() 272 | chip.set('option', 'clean', not resume) 273 | chip.set('option', 'breakpoint', floorplan and not remote, step='floorplan') 274 | 275 | _run_build(chip, remote) 276 | 277 | if verify: 278 | _run_signoff(chip, 'write.views', 'write.gds', remote) 279 | 280 | _setup_core_module(chip) 281 | 282 | return chip 283 | 284 | 285 | def _setup_top_flat(): 286 | chip = siliconcompiler.Chip('zerosoc') 287 | chip.set('option', 'entrypoint', 'asic_top') 288 | 289 | chip.use(skywater130_demo) 290 | chip.set('option', 'flow', 'asicflow') 291 | 292 | chip.add('option', 'define', 'SYNTHESIS') 293 | chip.use(zerosoc_top) 294 | chip.use(zerosoc_core) 295 | 296 | chip.use(sky130io) 297 | chip.use(sky130sram) 298 | chip.set('asic', 'macrolib', ['sky130_sram_1rw1r_64x256_8', 'sky130io']) 299 | chip.swap_library('lambdalib_ramlib', 'lambdalib_sky130sram') 300 | chip.swap_library('lambdalib_iolib', 'lambdalib_sky130io') 301 | 302 | # Ignore cells in these libraries during DRC, they violate the rules but are 303 | # foundry-validated 304 | for task in ('extspice', 'drc'): 305 | chip.add('tool', 'magic', 'task', task, 'var', 'exclude', 'sky130io') 306 | chip.add('tool', 'netgen', 'task', 'lvs', 'var', 'exclude', 'sky130io') 307 | 308 | # OpenROAD settings 309 | chip.set('tool', 'openroad', 'task', 'macro_placement', 'var', 'rtlmp_enable', 'true') 310 | chip.set('option', 'var', 'openroad_grt_macro_extension', '0') 311 | for task in _get_tool_tasks(chip, openroad): 312 | chip.add('tool', 'openroad', 'task', task, 'var', 'psm_skip_nets', 'ioring*') 313 | chip.add('tool', 'openroad', 'task', task, 'var', 'psm_skip_nets', 'v*io') 314 | 315 | chip.set('tool', 'yosys', 'task', 'syn_asic', 'var', 'hierarchy_separator', '.') 316 | chip.clock(r'padring.iwest.ipad\[3\].gbidir.i0.gpio/IN', period=60) 317 | 318 | zerosoc_floorplan.generate_top_flat_floorplan(chip) 319 | 320 | return chip 321 | 322 | 323 | def _setup_top_hier(core_chip): 324 | chip = siliconcompiler.Chip('zerosoc_top') 325 | 326 | if not core_chip: 327 | if not os.path.exists(ASIC_CORE_CFG): 328 | print(f"'{ASIC_CORE_CFG}' has not been generated.", file=sys.stderr) 329 | return 330 | core_chip = siliconcompiler.Library('zerosoc_core') 331 | core_chip.read_manifest(ASIC_CORE_CFG) 332 | core_chip.set('design', 'asic_zerosoc_core') 333 | 334 | chip = siliconcompiler.Chip('zerosoc_top') 335 | chip.set('option', 'entrypoint', 'asic_top') 336 | 337 | chip.use(skywater130_demo) 338 | chip.set('option', 'flow', 'asicflow') 339 | 340 | chip.use(core_chip) 341 | chip.use(zerosoc_top) 342 | chip.use(sky130io) 343 | chip.set('asic', 'macrolib', [core_chip.design, 'sky130io']) 344 | chip.swap_library('lambdalib_iolib', 'lambdalib_sky130io') 345 | chip.swap_library('zerosoc_core', None) 346 | 347 | # Ignore cells in these libraries during DRC, they violate the rules but are 348 | # foundry-validated 349 | for task in ('extspice', 'drc'): 350 | chip.add('tool', 'magic', 'task', task, 'var', 'exclude', 'sky130io') 351 | chip.add('tool', 'netgen', 'task', 'lvs', 'var', 'exclude', 'sky130io') 352 | 353 | for tool in core_chip.getkeys('tool'): 354 | for task in core_chip.getkeys('tool', tool, 'task'): 355 | if core_chip.valid('tool', tool, 'task', task, 'var', 'exclude'): 356 | exclude = core_chip.get('tool', tool, 'task', task, 'var', 'exclude') 357 | chip.set('tool', tool, 'task', task, 'var', 'exclude', exclude) 358 | 359 | # OpenROAD settings 360 | chip.set('option', 'var', 'openroad_grt_macro_extension', 0) 361 | 362 | for met, adj in (('met2', 0.2), 363 | ('met3', 0.1), 364 | ('met4', 0.1), 365 | ('met5', 0.1)): 366 | chip.set('pdk', 'skywater130', 'var', 'openroad', f'{met}_adjustment', '5M1LI', str(adj)) 367 | 368 | for task in _get_tool_tasks(chip, openroad): 369 | chip.add('tool', 'openroad', 'task', task, 'var', 'psm_skip_nets', 'ioring*') 370 | chip.add('tool', 'openroad', 'task', task, 'var', 'psm_skip_nets', 'v*io') 371 | chip.set('tool', 'yosys', 'task', 'syn_asic', 'var', 'hierarchy_separator', '.') 372 | 373 | zerosoc_floorplan.generate_top_floorplan(chip) 374 | 375 | return chip 376 | 377 | 378 | def build_top_flat(resume=True, remote=False, floorplan=False): 379 | project = ASIC(ZeroSOC()) 380 | project.add_fileset("rtl.top") 381 | project.add_fileset("sdc.top.sky130") 382 | 383 | skywater130_demo(project) 384 | project.set_flow(SV2VASICFlow()) 385 | 386 | init_fp: InitFloorplanTask = get_task(project, filter=InitFloorplanTask) 387 | init_fp.add_openroad_padringfileset("padring.sky130") 388 | 389 | for task in get_task(project, filter=APRTask): 390 | task.add_openroad_globalconnectfileset("zerosoc", "globalconns.flattop") 391 | 392 | get_task(project, filter=PowerGridTask).add_openroad_powergridfileset("zerosoc", "pdn.flattop") 393 | 394 | for task in get_task(project, filter=OpenROADPSMParameter): 395 | task.add("var", "psm_skip_nets", 'ioring*') 396 | task.add("var", "psm_skip_nets", 'v*io') 397 | 398 | project.constraint.area.set_diearea_rectangle(1700, 2300, coremargin=230) 399 | # chip = _setup_top_flat() 400 | 401 | project.set('option', 'clean', not resume) 402 | 403 | project.set('option', 'breakpoint', floorplan and not remote, step='floorplan') 404 | 405 | project.run() 406 | project.summary() 407 | 408 | return project 409 | 410 | 411 | def build_top(core_chip=None, verify=True, resume=False, remote=False, floorplan=False): 412 | chip = _setup_top_hier(core_chip) 413 | 414 | chip.set('option', 'clean', not resume) 415 | chip.set('option', 'breakpoint', floorplan and not remote, step='floorplan') 416 | 417 | _run_build(chip, remote) 418 | if verify: 419 | _run_signoff(chip, 'write.views', 'write.gds', remote) 420 | 421 | return chip 422 | 423 | 424 | def _run_build(chip, remote): 425 | if remote: 426 | _configure_remote(chip) 427 | 428 | chip.run() 429 | chip.summary() 430 | 431 | 432 | def _run_signoff(chip, netlist_step, layout_step, remote): 433 | gds_path = chip.find_result('gds', step=layout_step) 434 | netlist_path = chip.find_result('vg', step=netlist_step) 435 | 436 | jobname = chip.get('option', 'jobname') 437 | chip.set('option', 'jobname', f'{jobname}_signoff') 438 | chip.set('option', 'flow', 'signoffflow') 439 | 440 | # Hack: workaround the fact that remote runs alter the steplist 441 | if chip.get('option', 'remote'): 442 | chip.set('option', 'steplist', []) 443 | 444 | chip.input(gds_path) 445 | chip.input(netlist_path) 446 | 447 | _run_build(chip, remote) 448 | 449 | 450 | def _main(): 451 | parser = argparse.ArgumentParser(description='Build ZeroSoC') 452 | # parser.add_argument('--fpga', 453 | # action='store_true', 454 | # default=False, 455 | # help='Build FPGA bitstream.') 456 | parser.add_argument('--core-only', 457 | action='store_true', 458 | default=False, 459 | help='Only build ASIC core GDS.') 460 | parser.add_argument('--top-only', 461 | action='store_true', 462 | default=False, 463 | help='Only integrate ASIC core into padring. Assumes core already built.') 464 | parser.add_argument('--top-flat', 465 | action='store_true', 466 | default=False, 467 | help='Build the entire ZeroSoC.') 468 | parser.add_argument('--floorplan', 469 | action='store_true', 470 | default=False, 471 | help='Break after floorplanning.') 472 | parser.add_argument('--verify', 473 | action='store_true', 474 | default=False, 475 | help="Run DRC and LVS.") 476 | parser.add_argument('--remote', 477 | action='store_true', 478 | default=False, 479 | help='Run on remote server. Requires SC remote credentials.') 480 | parser.add_argument('--clean', 481 | action='store_true', 482 | default=False, 483 | help='Clean previous run.') 484 | options = parser.parse_args() 485 | 486 | verify = options.verify 487 | 488 | if options.core_only: 489 | build_core(remote=options.remote, 490 | verify=verify, 491 | resume=not options.clean, 492 | floorplan=options.floorplan) 493 | elif options.top_only: 494 | build_top(verify=verify, 495 | remote=options.remote, 496 | resume=not options.clean, 497 | floorplan=options.floorplan) 498 | elif options.top_flat: 499 | build_top_flat(remote=options.remote, 500 | resume=not options.clean, 501 | floorplan=options.floorplan) 502 | else: 503 | core_chip = build_core(remote=options.remote, 504 | verify=False, 505 | resume=not options.clean, 506 | floorplan=options.floorplan) 507 | build_top(core_chip=core_chip, 508 | remote=options.remote, 509 | verify=verify, 510 | resume=not options.clean, 511 | floorplan=options.floorplan) 512 | 513 | 514 | if __name__ == '__main__': 515 | _main() 516 | -------------------------------------------------------------------------------- /random.mem: -------------------------------------------------------------------------------- 1 | 31de4ca0 2 | ab6cb03b 3 | 59922e7b 4 | 23f98b2c 5 | 3e4ca4f0 6 | 852541d1 7 | 62379d99 8 | 2881b8c6 9 | b8284c34 10 | 5baf29f1 11 | 0803a278 12 | a5688d83 13 | 03f457e7 14 | 6b779a73 15 | 90db6adf 16 | 887ba464 17 | b9a66989 18 | 8129d602 19 | 8078f8f8 20 | 84847238 21 | 26fa696f 22 | fbaca60f 23 | 5a473075 24 | d5fed5d0 25 | 74c43599 26 | 338d26b3 27 | 25d5507a 28 | a6869726 29 | c34464bb 30 | 21b086f7 31 | c3e5554b 32 | 4ab0e202 33 | 080639ef 34 | ce161d67 35 | 4d3cc8ee 36 | 8f1b7b34 37 | 474a5b5d 38 | 0d1bb664 39 | 8f7e7dc7 40 | c80dca29 41 | 79d29fac 42 | 27caade9 43 | 2d97cb03 44 | e6cb5b35 45 | a90652fa 46 | ab9c2f80 47 | 7284226e 48 | 53af15c1 49 | 368f3bc7 50 | 94a6da31 51 | 93f0ade5 52 | c9e2d220 53 | b1621a96 54 | e92ab326 55 | 356bf7a1 56 | 4a4d9196 57 | aee5b290 58 | 04595c85 59 | 51cacd34 60 | c347a8a6 61 | bb83b6a6 62 | d6b60fca 63 | 2c415965 64 | c3fa2797 65 | 7e573d34 66 | 4dd5f7aa 67 | 642157e6 68 | 748c66dc 69 | 889763ed 70 | 9a9d4fbb 71 | 5d8fb797 72 | 07fd31b6 73 | db481bde 74 | 597ebb8c 75 | 7755b49c 76 | 982749b1 77 | 455a1314 78 | 87119ac8 79 | 5ca4afab 80 | 0d53aa78 81 | 7c42cad8 82 | 2e286c7e 83 | 7e93d672 84 | bba33143 85 | 1956b2f9 86 | aa8756dc 87 | 1f34f7b1 88 | 015404e0 89 | deda1216 90 | 4fc1761e 91 | 7490bc87 92 | 0626dfeb 93 | 0e6af14d 94 | b301fc40 95 | b989d9dc 96 | 0416dc79 97 | 7f089424 98 | e3da9bdc 99 | 740deade 100 | 93e5c58f 101 | b86d28ae 102 | 447dd537 103 | 522532ee 104 | cdaf5a37 105 | 3bff4525 106 | 9ef0181a 107 | e9392082 108 | 262df939 109 | 0ed4e471 110 | 76532116 111 | a26a3969 112 | 84f4ab48 113 | a67cf4fb 114 | 94060aff 115 | cd7e6e21 116 | 1171face 117 | 1f294bea 118 | f8eba470 119 | 1ebbf6e7 120 | 34063275 121 | 93cf0526 122 | 7a90d5dc 123 | c64b3561 124 | 59c2f3d8 125 | e7af2759 126 | d707a294 127 | 17f3c15f 128 | 1e0ae276 129 | 583c9350 130 | 05ce507c 131 | 9b34b4e2 132 | ba0d7dd8 133 | 17fc2883 134 | c8742841 135 | e18d7dff 136 | f68a83e6 137 | c0bfa535 138 | 92f85575 139 | e5de6b7c 140 | 37013648 141 | 80ca757b 142 | 23f13420 143 | 2940cc8e 144 | 64258206 145 | 45ef37a8 146 | 7d81f82b 147 | b3a7836d 148 | b337a6a5 149 | f562c5be 150 | d9647356 151 | 271c2a27 152 | de1c7346 153 | 315b2f8b 154 | d1f9b882 155 | a03d3e4d 156 | a0c691bf 157 | 8c9c333b 158 | 1c166627 159 | 405694dc 160 | 36c7025d 161 | 160d537c 162 | 949650db 163 | 4b5b0c06 164 | ff2ea3dc 165 | 10ddbdcd 166 | 4487f293 167 | 70bc47aa 168 | 1d4482bb 169 | 5cb5f425 170 | db43d1c0 171 | ceaf9339 172 | 427db833 173 | 4f2311ab 174 | 72746294 175 | f3584efa 176 | 31ea5fc9 177 | bbd79948 178 | d27bf251 179 | 29499bc3 180 | df311ca3 181 | f6f95f88 182 | f34dd952 183 | 28d3db42 184 | b2b1a5b1 185 | 4dab1412 186 | d5af89fd 187 | 3d822aba 188 | 05c2fe8f 189 | 0b17aa8a 190 | f8d48e1f 191 | 287048ab 192 | dc6e47ad 193 | af880bd7 194 | 6267e49c 195 | 55069254 196 | 52c3a003 197 | 820183aa 198 | 291e441b 199 | 1c82c8f8 200 | eb967f15 201 | d15eac3c 202 | 6eb81b09 203 | 5f286b7e 204 | 1404cdfc 205 | fecd361d 206 | 572b9127 207 | aab856e8 208 | 29c2bb44 209 | 35176a19 210 | 26c08685 211 | ee31a79b 212 | 5ebf429e 213 | 775be76c 214 | ee286784 215 | 3a93ef6a 216 | f06edf21 217 | c75d2afb 218 | 64fb65d8 219 | c83bf1d1 220 | c7cb25c3 221 | b2b50b7c 222 | 8ec5dede 223 | eb218801 224 | 84757ec2 225 | b632e929 226 | 0c302ec3 227 | 75d4a699 228 | 9535f114 229 | 74810e5a 230 | 1bfc8406 231 | b8055660 232 | c3d620a2 233 | c4079277 234 | e04bf556 235 | 352f39aa 236 | 13cc0a9b 237 | deac109c 238 | 1dc5f9a9 239 | 30a2eaab 240 | 5189bb3a 241 | 69591faa 242 | 457a6cf6 243 | 5dab1abc 244 | 8d89fcf7 245 | 04d72291 246 | 0d64aad7 247 | 8ded447e 248 | a47277ba 249 | 7a0037e4 250 | 567d6d14 251 | 5f41347f 252 | d3bbebe6 253 | 459bdb29 254 | e19038d8 255 | 0e1e75d9 256 | 80d0d0c1 257 | 0303b74f 258 | 10c21a58 259 | c563555a 260 | 9e0bf662 261 | f2670a5b 262 | 5a6f4864 263 | 1547b6a9 264 | 3a405118 265 | 1d829c8c 266 | 766aeab7 267 | f3bf0733 268 | c7c20b7b 269 | 59ce043b 270 | e6a538c4 271 | 4eb269c0 272 | 981027ef 273 | f08c1e53 274 | 1a5653cd 275 | 138fa060 276 | 398caf10 277 | 64b2b3f3 278 | 944e75b5 279 | 1a4285ac 280 | 08c3c8eb 281 | e411305a 282 | 13c6df8d 283 | 17a6595c 284 | b63bcf8c 285 | b5ead8e9 286 | afb70010 287 | 22e96bf8 288 | bd6625e3 289 | 7e75f0e6 290 | 09a1c6e5 291 | 34e3ae49 292 | ea73a80c 293 | 57f15703 294 | 6fe42435 295 | 9957fe9e 296 | 88fde9fe 297 | 06027154 298 | e320c689 299 | 5401f6fc 300 | 21946c26 301 | 06b12df9 302 | 26aa7ff1 303 | 687aab07 304 | e3f9a9be 305 | 64614dc3 306 | 70ee9296 307 | 12b65d07 308 | 5142b6f9 309 | 4fff93bd 310 | 62a5a0ed 311 | 4fd48763 312 | 5c5a13dc 313 | f9ad3890 314 | c19fe5d8 315 | 03131630 316 | bcf4f93b 317 | e7ba9c5e 318 | 7c129bdb 319 | d2cc765f 320 | 927c25b4 321 | 26214686 322 | 7ccc9163 323 | 67c4b79b 324 | bfe02d08 325 | ced1168e 326 | 12e612fc 327 | 28d1b1ab 328 | f3407f08 329 | 8f90ea73 330 | 33717a6f 331 | 199c1aae 332 | 2effbf19 333 | 232e8d8f 334 | 289d4c58 335 | 043780c2 336 | ab87534f 337 | a7aa4b53 338 | 878ad4d4 339 | 038e3ee1 340 | dae76009 341 | 64f0086f 342 | 7bbbf0c6 343 | 7ebc1160 344 | a137e2f8 345 | a992b85d 346 | 55767c98 347 | 4aecbb94 348 | 060e0e88 349 | e0e765c4 350 | eef04f0d 351 | c9dec1de 352 | 45dd5217 353 | 5fb160f1 354 | b610ccf6 355 | 048a8acd 356 | dfc42af6 357 | 1e9339f5 358 | 19664d2f 359 | cb800500 360 | 5c32deb9 361 | 56550ca6 362 | 7ee50bd2 363 | b2e0b6a4 364 | b015d85c 365 | 6feeee21 366 | 4c1ddf76 367 | 0e2d0d5a 368 | 25ab48b9 369 | ac867d0c 370 | 58a92247 371 | 7f597d1e 372 | c38ebd6b 373 | 87f36624 374 | 911b4a28 375 | 25ffcaa5 376 | 894b3a9a 377 | bd54754e 378 | 7a90ad02 379 | 54e41784 380 | 3148b0af 381 | 0f2c6656 382 | bceef685 383 | b428fa04 384 | c8a96e5c 385 | 6563cc8a 386 | 46b7e808 387 | e02107ff 388 | 0ec34acc 389 | 402563f6 390 | 31a407bf 391 | af6a11af 392 | 52cb70a4 393 | 18b8ad15 394 | 433d76b9 395 | aae2b669 396 | 8e6af4dc 397 | 3960f5d3 398 | 55eb84f7 399 | 6b9dbc17 400 | a30c016f 401 | 057d21c4 402 | bfdb3b82 403 | 274eb7d5 404 | 9355a7b7 405 | 0d63aa59 406 | 3318f7b3 407 | 1214c2df 408 | 2f148188 409 | 87e5786a 410 | e712da4b 411 | 2e3a2f5a 412 | 56edbeff 413 | 2dbb8d63 414 | ece0b70d 415 | 09bb9451 416 | 5fa278eb 417 | a78351ad 418 | 192e09a2 419 | 695bd0a0 420 | c650d280 421 | d56b8b34 422 | 88fc1575 423 | 5fcc4229 424 | 955ed999 425 | a520d004 426 | 581d5528 427 | 75c5ba10 428 | bf848c65 429 | d06d8498 430 | c217202c 431 | 91890551 432 | 50bd45b5 433 | e3a1e8b4 434 | 13382c65 435 | bef9bcf2 436 | 635ea069 437 | 0a39daa2 438 | 99bdb0c8 439 | b5079e64 440 | 8b4f0e9b 441 | e0c857b8 442 | 428f788e 443 | 0621ef67 444 | a26392af 445 | ee42b155 446 | 44c9658b 447 | 74ed3215 448 | 7eb875d9 449 | a1269215 450 | df4624a4 451 | 8d5db47f 452 | ca1846da 453 | 21800a52 454 | 5b64014f 455 | e2272bd6 456 | 900d4a94 457 | 9fd10503 458 | 6e2a635d 459 | 7284a727 460 | a991c55e 461 | 6bb5269b 462 | 122fb04e 463 | c10c94c8 464 | b34b306c 465 | eaf557aa 466 | c0d3cc81 467 | 0a7972d9 468 | ee542e0e 469 | 9ab5a6fc 470 | 9fa94be7 471 | 98af8629 472 | 29aa3e5b 473 | 39bda06b 474 | 0dc0a40f 475 | 4622245e 476 | 81b0c4ee 477 | afda16cb 478 | ce6b623c 479 | 8de1f447 480 | 541f7fbf 481 | c8349f1f 482 | a24ea156 483 | b85f3b1b 484 | 8caab375 485 | 98f07053 486 | 9babc910 487 | 0f85d68c 488 | c1a17860 489 | b683e238 490 | ca9700f9 491 | 606dcab9 492 | ee3c07ea 493 | 6112be65 494 | a97b4494 495 | 2e942d62 496 | 2d9c0ca1 497 | bab8d85b 498 | 5c31f95a 499 | ac58b6d1 500 | 8449babd 501 | 51206296 502 | aef8756e 503 | e21d0f78 504 | 573fdaac 505 | 766dbaad 506 | f3cef498 507 | 8544762a 508 | e975ff6c 509 | 3f2b343b 510 | bae634af 511 | e3924b78 512 | 7166cf1f 513 | 85a07b56 514 | a0f84fa2 515 | aa011e1d 516 | 05aef8c1 517 | dbdda1f0 518 | 99498f28 519 | 6a7097dc 520 | 8dd2b797 521 | 1e4b11cf 522 | a8c80ba5 523 | 82c37971 524 | 266fa432 525 | 7d9c6742 526 | 6d9fdfaa 527 | 138cce64 528 | 7d15b102 529 | 5696a993 530 | 8f28c41e 531 | c08214d9 532 | fd9bc03a 533 | ce761ed9 534 | 6e3ba87c 535 | 44264d6f 536 | d2abbc6d 537 | d0b902e0 538 | dcf38408 539 | ca6806ac 540 | 62fe5008 541 | b60e59ba 542 | a6815827 543 | ec853b4a 544 | 09c511d7 545 | c9e19001 546 | 2c55a49d 547 | 8459fd7d 548 | 01cb94ba 549 | c2bfa36b 550 | 1949965d 551 | ca8ab15a 552 | 44bcd85e 553 | 7828e483 554 | 199aa665 555 | 69ee2e9e 556 | fde69c44 557 | 0cebf2d9 558 | bf106c56 559 | 5435f59f 560 | 1202cc58 561 | 27cb5cdc 562 | 350f1d8d 563 | a453a4e1 564 | 71cc1538 565 | 8b632d68 566 | 19222a73 567 | db2c5f70 568 | c7d31852 569 | 207a737a 570 | 54998249 571 | c85f6512 572 | 23305670 573 | b46f0101 574 | eded061e 575 | 283e1fee 576 | a85da396 577 | 52b1cdf9 578 | 9ceb35c7 579 | a6115fba 580 | 3789f145 581 | 19a9dfca 582 | fa964543 583 | 240fc805 584 | 7b308928 585 | 77271235 586 | 4e6f3f30 587 | c90b9a9d 588 | 65b037cf 589 | 6a57cbb9 590 | 37d9831d 591 | 3e39d035 592 | 8cab3803 593 | f82999e8 594 | 17723301 595 | 2cdbde92 596 | 36bfc140 597 | c6657b9a 598 | 7cd26117 599 | 93fd3f09 600 | d3d78b79 601 | ad1e24d5 602 | 834a39a4 603 | 933c35f7 604 | 1ef7db9c 605 | 04ab35a3 606 | 68e3532a 607 | 3dd2fed9 608 | e0a8d3d2 609 | f32d18fa 610 | 4f92ee39 611 | 2bf28a1f 612 | 7e0294f5 613 | 6427c961 614 | 460e6613 615 | 039bf0a8 616 | 8f381b78 617 | fcda49de 618 | f169f472 619 | 4b0fa511 620 | 527fcdb6 621 | 47fdd4e0 622 | ee98e68b 623 | d5c01f2e 624 | 0cd7ac69 625 | 10864a3a 626 | 26f9856e 627 | f111cfe7 628 | 235a2455 629 | fbdaf084 630 | 46017d51 631 | f2220220 632 | ba51fec3 633 | ee8bb25a 634 | 1f03888e 635 | f981a0fb 636 | 62657b96 637 | 94e617a6 638 | 61797dcf 639 | 2b72ec93 640 | a8fac438 641 | 60dff281 642 | a1b89600 643 | aff6c427 644 | 7391abe2 645 | 2ae53a40 646 | 01d7943e 647 | 9f3d3e75 648 | e140d1b3 649 | e2184f03 650 | eff122a0 651 | 3bda5515 652 | 419540b9 653 | b9f9f138 654 | 1fbf76f9 655 | aa497ff7 656 | 8c6839a2 657 | c483baaf 658 | 5b680467 659 | 9bc691c4 660 | 19e811a1 661 | fc8c0ba6 662 | 1dcec571 663 | b1ef1705 664 | e2face0a 665 | f2092b78 666 | e50f59e1 667 | 1d52dbf6 668 | 436b28b5 669 | 91653667 670 | 9ae6576b 671 | 1e8694c5 672 | b6281a2f 673 | 15a9fc74 674 | 535281af 675 | 8324b14f 676 | 129431b9 677 | 94a7a7ac 678 | a6e5edea 679 | f907a87d 680 | 08c9247d 681 | 970a4b6b 682 | 4732b7a3 683 | 8365d8c1 684 | 4af71069 685 | ed864f43 686 | e8cbafb4 687 | 73502a2c 688 | 0b423bab 689 | 6dfebf3d 690 | 2947de2f 691 | 21a2c542 692 | 043aba67 693 | c95ead54 694 | 5b9de8bf 695 | 2b5376d1 696 | e2c912af 697 | 9b0082e3 698 | 17a925ae 699 | ae8bd00b 700 | 950ad2d5 701 | 144513d2 702 | b0ada2b7 703 | dd130a4e 704 | 0c61e599 705 | b12e20fd 706 | 071dc17c 707 | b398983b 708 | 637790f8 709 | 8b37c43d 710 | dad7002b 711 | ee1beecd 712 | b52c5eb7 713 | f7d0d8f4 714 | ee6b6e3e 715 | 10899f46 716 | 7939fd53 717 | c25ce882 718 | e7d96f14 719 | b722bafe 720 | 86d6bf29 721 | e2797fa5 722 | c3d081fd 723 | 84e0697f 724 | f28d698d 725 | fc44e7d8 726 | 7ef4f7d4 727 | ed5fea71 728 | fa63654f 729 | 3e83a6b1 730 | 39a324ba 731 | 33456fd2 732 | 5aab2248 733 | 64546ac8 734 | fd065814 735 | 512964e4 736 | d0a9661c 737 | c129a741 738 | 6f2fd6d1 739 | 848881c5 740 | ca83aa65 741 | 341850b9 742 | 1a9fbbc9 743 | ec49103a 744 | d5dd9099 745 | db1a1986 746 | 2f1d0479 747 | 613ff9c3 748 | 3cc546d9 749 | bceb8fc5 750 | b993ff70 751 | e74cc15c 752 | 678ea954 753 | 8eecfd6d 754 | 9fd3afce 755 | 0aad477c 756 | 4bea5c1f 757 | 29d72dde 758 | fe9bf26a 759 | a04c4094 760 | c253f92c 761 | d316464b 762 | 2fce332a 763 | 95baf168 764 | 49dd3e06 765 | d8729f09 766 | 67116f08 767 | 0b58ff31 768 | 0a78b18d 769 | 4c9e99d9 770 | 0e51c2d9 771 | 939f9f47 772 | 3877bc24 773 | 38461513 774 | e6ca137f 775 | 67bcefc5 776 | 449602ff 777 | 3c544c6c 778 | 9d785f61 779 | e47a055b 780 | c6eb811f 781 | 2ebae639 782 | 7becf48a 783 | 9c2dec80 784 | 8ca02978 785 | 0f6f780b 786 | 63c97867 787 | 190198fc 788 | 210a59cb 789 | 2ecafec4 790 | a77980dd 791 | 129945f7 792 | bfa76428 793 | f3397888 794 | fb51416c 795 | 10b793ff 796 | 641d20f2 797 | f8df7801 798 | 1cf5653b 799 | afab57c2 800 | 58291aa3 801 | ccd123e8 802 | 325efa00 803 | 6e486757 804 | 27f1b677 805 | 7984fab4 806 | 562c1b21 807 | a646d833 808 | 14733563 809 | f78830ab 810 | fa484ba4 811 | be516baa 812 | 22f40c41 813 | 9003d06a 814 | 5a7ea967 815 | b3b0e82a 816 | 22f6530d 817 | 156abc27 818 | c3714ef3 819 | 0bbf4434 820 | bb21dc6a 821 | e2f68671 822 | 162875a9 823 | eb15ef32 824 | 493d0892 825 | dc2dce24 826 | 8a53c7e9 827 | 1241ead8 828 | 9704b5c6 829 | e6f2c323 830 | 7b9ca600 831 | 9a26401b 832 | d960106b 833 | c98f5514 834 | 4ee4457e 835 | 2ded2e2a 836 | 8a0bef87 837 | 4b412979 838 | 7ac000b7 839 | c0f199ed 840 | e76e8182 841 | 73a692aa 842 | 5c4dbf25 843 | 33ec2224 844 | 2dab1227 845 | f5893b48 846 | ce28cb17 847 | 0e9dbbca 848 | b98d8aa0 849 | 2da65784 850 | ddf45e05 851 | 26e05c38 852 | d5ee9c2b 853 | 59b07a5f 854 | f7f9ff82 855 | fb2128b7 856 | e2ab7d69 857 | af112548 858 | d399d1f1 859 | 95818290 860 | ff3c692c 861 | 6f7f9fb0 862 | a3c66164 863 | ccbcc475 864 | 8a669e88 865 | 43905c70 866 | 007c43ab 867 | 19d2ad0a 868 | 37505254 869 | 07e0358f 870 | a490ab9e 871 | 29e7a173 872 | 700b1c69 873 | 79c33f86 874 | a55b29df 875 | e340f91c 876 | 4c2dc5e7 877 | 470658e7 878 | 7ae832a7 879 | 5817f89c 880 | e69ddaa2 881 | a6af6e05 882 | c20753ad 883 | b3729324 884 | a60dff44 885 | b996a97b 886 | cbc67473 887 | 6c825d29 888 | 2d9edb11 889 | 7ae70191 890 | 5744dd6c 891 | 6ce7a9f6 892 | cc372001 893 | 491909a0 894 | 78f674c6 895 | e422f400 896 | acfe5cb3 897 | bb72f981 898 | fa0a8d93 899 | 564d127a 900 | cc0bd4e6 901 | 111a29a8 902 | 485fe21b 903 | b973822e 904 | e3d38b5c 905 | ab5df888 906 | 455370bc 907 | 50d0d70a 908 | 6ce20c06 909 | 2452a812 910 | e9d45e1a 911 | d07e1add 912 | 7ffb1dfe 913 | d5367b3e 914 | 93173f77 915 | a8bd8cb6 916 | cfa8513f 917 | 2617f48b 918 | e7799c89 919 | f7292d6d 920 | 0a88f2e7 921 | c321e63b 922 | 318562a6 923 | c0886a3e 924 | bd572781 925 | a0ef1162 926 | f5c4132b 927 | 4a08b205 928 | 59e358c7 929 | 33560e75 930 | 2a9c7ba8 931 | 7c781fd8 932 | 2fc2080a 933 | 7133a831 934 | daa8b322 935 | 3feb801e 936 | bb39d694 937 | c2d7ddfc 938 | 47cb9453 939 | 5b08506e 940 | e0cd85f6 941 | a150358e 942 | 2e1cc0ee 943 | 794fd371 944 | e54b2610 945 | a1dd8ea3 946 | 6d7cc7d2 947 | 5934e608 948 | ef3356df 949 | f277aca1 950 | b1c83499 951 | 2b5316ac 952 | a4d5e697 953 | 2db620d5 954 | 1d9b6b97 955 | 25eb1516 956 | 43de2103 957 | 59da409d 958 | 92fd8193 959 | ff84c1d5 960 | 85e4d3a0 961 | 892cfe78 962 | 51e32661 963 | 2c7c45ab 964 | 824a10cf 965 | add33556 966 | f222bb70 967 | 65441e4a 968 | 997cc939 969 | 311dfb8c 970 | cb8a0728 971 | 1f785009 972 | 136ddfe6 973 | 14502208 974 | 24523811 975 | c74e80f1 976 | e03d2b02 977 | aa4102d1 978 | 6466c89c 979 | 18e80e0d 980 | affd204a 981 | 2ccb192b 982 | 21e5faca 983 | 78950d46 984 | def4774f 985 | 2fa0ac5a 986 | 4873ca08 987 | 5bdc2937 988 | 5c509e1b 989 | b5a27783 990 | d5e87ca8 991 | 41dc03bd 992 | 64ef9922 993 | 07849a6b 994 | c238f9bd 995 | ad158a80 996 | 2d643a4b 997 | 737cedb0 998 | 016ad004 999 | 92521a32 1000 | 36a2028f 1001 | 4656944f 1002 | b7879e29 1003 | ec91d119 1004 | 293c4390 1005 | acd8ae44 1006 | 555cb3d2 1007 | 6ad67622 1008 | a3f67c2f 1009 | 3d75cd4a 1010 | cfab9280 1011 | fe37991d 1012 | 961fb546 1013 | 4f9e88da 1014 | 1b1c3d7a 1015 | c96f189c 1016 | 138ebbc6 1017 | 20179de7 1018 | b3135e5b 1019 | 24fabaa1 1020 | 863b0dba 1021 | e273581b 1022 | b5cedb29 1023 | 56ecfa00 1024 | 6f22d480 1025 | b90b4bed 1026 | 830b9fb9 1027 | 29c9c090 1028 | f66cd844 1029 | 708b7342 1030 | fcb1d3d2 1031 | da399ffc 1032 | 34250e34 1033 | e8f02e56 1034 | f7e68fff 1035 | 7b2cc1a6 1036 | 7165c11a 1037 | eb077cac 1038 | c4509521 1039 | 5e94bf8b 1040 | f742c0e5 1041 | feefd9ad 1042 | b875d3e6 1043 | 4ddb3d13 1044 | d9c031dd 1045 | 97443ae1 1046 | 2bedbc73 1047 | dd8b1678 1048 | cbfb3cd9 1049 | 78e71584 1050 | a673d663 1051 | 77ffe1c7 1052 | b55bc07d 1053 | aea9b3d8 1054 | ef313749 1055 | f963af4e 1056 | 5e1b1931 1057 | 6c2e7afb 1058 | b68fe8d2 1059 | fbe0f163 1060 | a6616a36 1061 | 11353dfe 1062 | 946a71f8 1063 | aeef9ccd 1064 | b3c0540c 1065 | 6b32af04 1066 | 5b640b39 1067 | a9310d3c 1068 | c528be7b 1069 | b2aa9ec0 1070 | ce5f70e7 1071 | ed8cf6e1 1072 | ebfabf4c 1073 | 0247125d 1074 | c76a3ed6 1075 | 58decef4 1076 | f47cab1b 1077 | d970fb98 1078 | 0a6497f8 1079 | 24795d02 1080 | 915edb7b 1081 | d3a09467 1082 | ea161fbe 1083 | 7150910c 1084 | 7c219f28 1085 | 4b0f2bae 1086 | 4426d2a5 1087 | 6ff0a91f 1088 | c1310b83 1089 | b1496c4f 1090 | 5d73ca3a 1091 | f7e7e30b 1092 | b56ebd3a 1093 | 6260297e 1094 | c0a5dd2f 1095 | 97371d97 1096 | 414eb234 1097 | bbc72682 1098 | 8d8829a7 1099 | d30e8b5e 1100 | d1a23817 1101 | b7a7cd12 1102 | 0215888c 1103 | 5ae45fcd 1104 | 7480233f 1105 | 41ae583e 1106 | 3ecc7950 1107 | 277628f9 1108 | b5403956 1109 | d1b27b9e 1110 | 04409b63 1111 | 4c6ad2f0 1112 | 0ef38fb8 1113 | 75c2fcab 1114 | 9082442f 1115 | 0a2c019f 1116 | cf1322e0 1117 | da7f96f7 1118 | 01d91ddf 1119 | f63554f3 1120 | d102fc12 1121 | bd1512dc 1122 | e4951768 1123 | f378e36f 1124 | 3f274ba4 1125 | b89d4add 1126 | e5ee26e4 1127 | 12d608c3 1128 | e3361cfc 1129 | 45db188f 1130 | 8e7501e8 1131 | 59352bde 1132 | 1a51be66 1133 | 992980c2 1134 | f1c84091 1135 | b645f1ea 1136 | cdb61b43 1137 | 09a3ae1a 1138 | 10bfe3ab 1139 | fe836f55 1140 | 25138384 1141 | 6984b5e8 1142 | 67884d91 1143 | c45d1484 1144 | e35de33a 1145 | ac965bdc 1146 | 20694359 1147 | c449fc4b 1148 | f36e6ecb 1149 | 787315ec 1150 | d5464b95 1151 | 0719121f 1152 | edd8899e 1153 | bafba717 1154 | 518de39e 1155 | d5d8456b 1156 | c62ce89f 1157 | 2364b3f9 1158 | b347a029 1159 | 6b6863e8 1160 | f5feaba0 1161 | 72c4bac7 1162 | 7087a435 1163 | 9ab56a9d 1164 | c191ed1e 1165 | 71838484 1166 | 08baf635 1167 | f86cec2a 1168 | f0cd18c0 1169 | 34f93fb4 1170 | 8cbb1229 1171 | 1ede617c 1172 | 1a9cc00a 1173 | 6fa27b6f 1174 | 69bb9304 1175 | 733a03e0 1176 | f90eaac7 1177 | ab53eb7c 1178 | aae6cf0f 1179 | 477f162e 1180 | 696fd99c 1181 | 8f38cbb5 1182 | 4f01d9e6 1183 | 65b9c319 1184 | 84513a8f 1185 | 18d6c2a6 1186 | 206fd032 1187 | 75aed079 1188 | c8f27850 1189 | bb6f8b7f 1190 | 15702f40 1191 | d4a2a438 1192 | 02fba779 1193 | 77a315cd 1194 | 25f9687a 1195 | 28e35317 1196 | 2ccdc057 1197 | b6bca631 1198 | 7e5df260 1199 | a110eacc 1200 | 22ec7a8f 1201 | adaa0c9b 1202 | 5defdb7d 1203 | 55b7bb1d 1204 | 06ccc012 1205 | 76db5638 1206 | 83a1b545 1207 | c3af5768 1208 | 4940a947 1209 | e8ec8e33 1210 | 5436f411 1211 | bb0c4b05 1212 | c8953b14 1213 | d211e1ad 1214 | 0e7ec0a6 1215 | b0f62ec0 1216 | 2325a1a5 1217 | 2ee9f3eb 1218 | 2c8da700 1219 | 332d5a40 1220 | 0a6d0347 1221 | 06b7b677 1222 | f213cb57 1223 | e51a1f91 1224 | 3d2f41e9 1225 | 989e6417 1226 | 305a7523 1227 | dfe4d8df 1228 | 9d98ae3c 1229 | 2e2b3950 1230 | 9c48a766 1231 | 7ad8ead5 1232 | 4080bf0e 1233 | bd7b21e6 1234 | 59ea1e05 1235 | 2c7f05bc 1236 | 2eb18ca0 1237 | 6a137d52 1238 | 1dc03876 1239 | 35f3f7fe 1240 | 5b3a244b 1241 | 2470cc8e 1242 | 47362bbb 1243 | 83f468ac 1244 | fe0c0755 1245 | b97a3169 1246 | e611667c 1247 | 3229b24f 1248 | a2a103fe 1249 | 6010b6bd 1250 | 17196da9 1251 | ba4dc5af 1252 | 2449f5d0 1253 | a193dedd 1254 | be81bea0 1255 | d8aaf771 1256 | 3ee2a66a 1257 | f5279897 1258 | adcc6d37 1259 | 8365005c 1260 | 3357aa86 1261 | b4689a61 1262 | 477daa45 1263 | b7084ab7 1264 | 7ca92041 1265 | 4c33c832 1266 | aa585c09 1267 | 0f75dc60 1268 | 989dea57 1269 | d791dfab 1270 | 9fdfa9a7 1271 | a5fabc76 1272 | ae6b715c 1273 | c4863fa0 1274 | 395c4b82 1275 | b6fd7f66 1276 | 7e0cb1f6 1277 | c3f6c5d8 1278 | 210537e9 1279 | 871d06dd 1280 | 30a135d1 1281 | 13593857 1282 | 2199b20e 1283 | c82156da 1284 | 63194f9e 1285 | 5d939564 1286 | bd4a3405 1287 | a6a5b25d 1288 | adc9acc7 1289 | 5cbc6e2f 1290 | 7f3b6473 1291 | 52705486 1292 | a46e3309 1293 | d752645f 1294 | a10b5fef 1295 | 5f03b7bb 1296 | 49c366dd 1297 | 3ca80153 1298 | 3ff434eb 1299 | 4fdb1f82 1300 | dc3c0496 1301 | 1ab40d53 1302 | d22e2817 1303 | 999048e8 1304 | ebee5830 1305 | 4fdca91d 1306 | 7d9f6ee9 1307 | f8f6a76a 1308 | edb5fe87 1309 | f2097295 1310 | c9e00755 1311 | 76f329d5 1312 | 89337a15 1313 | 6813e0dd 1314 | 9b9d55a6 1315 | fa677710 1316 | 631aa9a0 1317 | a48d4d71 1318 | 8eada4ee 1319 | 02107727 1320 | 51faedc9 1321 | fe5abcdc 1322 | 06f5a189 1323 | ce080d7e 1324 | d34908cd 1325 | 0cbc772f 1326 | 6f000ac1 1327 | b743d60e 1328 | e1df56f7 1329 | fccfc988 1330 | 66c98160 1331 | e079d315 1332 | a7c4167b 1333 | 78618f2d 1334 | 9f818d2b 1335 | ffd313b3 1336 | 84ec0135 1337 | 13ff07ad 1338 | a067783d 1339 | dcea7fbf 1340 | ad842fa5 1341 | e549aa0f 1342 | 2940310d 1343 | 76312120 1344 | de7221ea 1345 | 166c3953 1346 | 6e0c4630 1347 | d0098191 1348 | fa110dcd 1349 | f01c55a1 1350 | 4021bb71 1351 | 8c422837 1352 | abd60817 1353 | 0057c646 1354 | 3b08735a 1355 | 26ee3c2b 1356 | 008970f6 1357 | 53191b68 1358 | ff861ffe 1359 | 66b0a6c4 1360 | 8d893be8 1361 | 62e0aa79 1362 | 21537363 1363 | 5a21f332 1364 | 312ebc31 1365 | 81b6f598 1366 | e75f34a9 1367 | fbd5ecc5 1368 | aa480526 1369 | 641a64f3 1370 | 3b6f2b6b 1371 | 655c9b9d 1372 | e3abbfa8 1373 | 4ec27e1b 1374 | 98afb044 1375 | b94091b3 1376 | 8d03d611 1377 | 0af3d7c8 1378 | 8c987626 1379 | b2079e65 1380 | 077c2caa 1381 | c9763a25 1382 | f1886c98 1383 | 4a4dfab2 1384 | c3e09f20 1385 | 9e95f24d 1386 | 0d7c1db0 1387 | a0f202dd 1388 | 47cb4016 1389 | 393f2f25 1390 | f754cfa2 1391 | e4e1563b 1392 | 3a475973 1393 | 7a385e9f 1394 | f54b6f03 1395 | d6a318b0 1396 | d0c8eee2 1397 | 9319c1db 1398 | 27a4c4e9 1399 | 3d66c8d3 1400 | 779de3f0 1401 | 56881b78 1402 | 1e48e4e4 1403 | 0f2a4aab 1404 | 58f5f2d0 1405 | e6f22421 1406 | 659f0049 1407 | 1acd6d50 1408 | 20ce73b9 1409 | 65b6f1ba 1410 | 55887a0b 1411 | 010a3174 1412 | c4dadc1a 1413 | 59f33891 1414 | 92c6f402 1415 | f2e282b9 1416 | d3b3c094 1417 | 0788fa9b 1418 | af6b4ef5 1419 | 5968c712 1420 | b99fd308 1421 | 2659c7a3 1422 | 873d60d7 1423 | 39e49902 1424 | 1a2bce2c 1425 | a2c371ad 1426 | bd61fa0b 1427 | fdae60b3 1428 | 651f5760 1429 | a5e52624 1430 | fbfe3ed8 1431 | 0e6ec18b 1432 | b251d76c 1433 | c364405d 1434 | 612085b9 1435 | ce389726 1436 | 1a2894f6 1437 | 2a69f695 1438 | 60e02f12 1439 | 3d2760f7 1440 | aaba194a 1441 | 3160b826 1442 | 0c08fca8 1443 | cebb3157 1444 | 03202db1 1445 | 4bf1d70c 1446 | ec905c45 1447 | 55599895 1448 | 3240d81d 1449 | 93aa6582 1450 | eb5b5d2b 1451 | f54c1074 1452 | 326932b8 1453 | 04352def 1454 | 08c3234e 1455 | 920e1c2f 1456 | 25896437 1457 | 6785eec3 1458 | a1a1d4bf 1459 | c314d3b6 1460 | 03c5f480 1461 | 5c0b8a37 1462 | 2bbc7e39 1463 | 70ee345e 1464 | 40f522b3 1465 | 30384de9 1466 | 480781fc 1467 | 7fdbbc59 1468 | 2e2fd4e3 1469 | e4ca7252 1470 | 59a0c63c 1471 | 20eabfb3 1472 | 893d0218 1473 | 2802fa7b 1474 | 0989539f 1475 | eecd03a6 1476 | bb01ab22 1477 | 49377e77 1478 | cbae1529 1479 | 1fbf5bc1 1480 | 5b19a427 1481 | 395c9a73 1482 | ae162fd8 1483 | e4d45d04 1484 | 5db4e201 1485 | 134ff3d1 1486 | 08276808 1487 | 0825eaa1 1488 | ea0bb19f 1489 | 5c226a03 1490 | 10f079a1 1491 | 4619a43f 1492 | ed8cd21f 1493 | 797b5e91 1494 | e4396829 1495 | 49ae3df7 1496 | 5bab60fa 1497 | 669f6d05 1498 | 7d68ecea 1499 | 81a7c2ab 1500 | 2427ef3d 1501 | 63981caa 1502 | 8479294f 1503 | c3139ca0 1504 | 22d66232 1505 | 29543084 1506 | e90a0dc5 1507 | 3d2c5cc3 1508 | 227e5772 1509 | cd463bac 1510 | 17e4e115 1511 | 95e0a239 1512 | 03bfdf8d 1513 | 98c89be1 1514 | 88ccfaab 1515 | ce83df8a 1516 | bb0f81c0 1517 | f40f9e6d 1518 | ae5da2f9 1519 | 836b22b5 1520 | 61a20de6 1521 | 830a453e 1522 | 35b18d7b 1523 | f86476fb 1524 | 1a12c6ca 1525 | 9e8c0957 1526 | 65ca75f9 1527 | 7655d369 1528 | 21e36bd9 1529 | 96ca8876 1530 | 936ccf0b 1531 | da7811c9 1532 | 71207f5c 1533 | 32646c7b 1534 | d8851b08 1535 | f3935232 1536 | be62f3bc 1537 | f3463c35 1538 | 4a31e701 1539 | d77544ee 1540 | fc0677c1 1541 | 6c01a3b0 1542 | 572aa8cd 1543 | b56f3fe4 1544 | 5715f4f0 1545 | b2d465da 1546 | f127a13c 1547 | 3bcfb53f 1548 | 1ddbebd9 1549 | 5236d14b 1550 | 0c70f4fb 1551 | a041649f 1552 | bb8e5b82 1553 | a912a7c1 1554 | 73e88a2d 1555 | 720aaa81 1556 | 54e4fb1d 1557 | c8b21a59 1558 | 8e61c07a 1559 | 602d9ed7 1560 | 4ef3e407 1561 | be7b06bc 1562 | 38ffa5a4 1563 | eafa706f 1564 | 32f9b0cd 1565 | 9eb036a2 1566 | 421dea13 1567 | e6e6bd4d 1568 | 65728bba 1569 | 58fff89e 1570 | 318a44ef 1571 | 76a8b4c3 1572 | 3863c013 1573 | a9d7b9f0 1574 | 20703dcc 1575 | 6c906ed6 1576 | ab62c1d5 1577 | 6c08b54e 1578 | 904c09e6 1579 | 29716e81 1580 | f6102081 1581 | 49af0ac3 1582 | 598388b8 1583 | 59fe21c6 1584 | 7dd13d67 1585 | 55103d80 1586 | b5f30c6e 1587 | 736d8137 1588 | ed23368f 1589 | 6dd5d3dd 1590 | 7bded1e7 1591 | 3ff1d0d5 1592 | 9822c0f1 1593 | 70e8ba28 1594 | d3bef04d 1595 | 03152560 1596 | eac1a8fc 1597 | 073e1e47 1598 | 16b85fb8 1599 | 1d5e5a9d 1600 | 5d9e6255 1601 | 39c33ce7 1602 | 6fb2be83 1603 | b0566983 1604 | 2264d325 1605 | 9a7ab9c1 1606 | b04371ca 1607 | ec13bff5 1608 | c646a6fe 1609 | 0dfce999 1610 | 9f900482 1611 | 1709579c 1612 | 539e3ef0 1613 | 78d13524 1614 | 937a01cd 1615 | b5bf497a 1616 | dc8d1d5f 1617 | 2a9367cd 1618 | e87cc07b 1619 | a83ce4c3 1620 | 47852c89 1621 | 07430048 1622 | 87b5b473 1623 | b859c227 1624 | cc50557e 1625 | d5c187e9 1626 | 606beaf0 1627 | 44cf66bb 1628 | cc16fd25 1629 | 77c52677 1630 | 6f0e30b3 1631 | 6b068c5e 1632 | 2a8ee0e4 1633 | 44785658 1634 | 7d91e2ce 1635 | 64b84f6a 1636 | cea3a088 1637 | 00ab22a2 1638 | 7a68dbcc 1639 | 288d4f52 1640 | 3dfd4868 1641 | 56d0f4c8 1642 | 64ee57b3 1643 | 1ebe01b9 1644 | 616dc578 1645 | bc02ce57 1646 | f5246fd6 1647 | dcde5905 1648 | 411ca5c0 1649 | 3787dbbd 1650 | e485fba0 1651 | bce511dd 1652 | c005c2a0 1653 | 94eb2f0e 1654 | f7955617 1655 | 871b533a 1656 | ded17ef7 1657 | 2b3c30c9 1658 | eff8654c 1659 | d62d37b9 1660 | fa10f576 1661 | caba7b99 1662 | ef2ce3bc 1663 | 085a03d9 1664 | e9162f7c 1665 | 04bf4ce2 1666 | fa56fd95 1667 | 632de2f8 1668 | 0b2edc72 1669 | 77b9517f 1670 | 0cd62d9c 1671 | 5cedb655 1672 | b4375ae4 1673 | e84b5ef4 1674 | 6952e1f9 1675 | 86db422f 1676 | 2beb6350 1677 | ab0fc1b2 1678 | 1c0e90cc 1679 | 0748907a 1680 | d0893ac9 1681 | f4185703 1682 | bdfd4cdf 1683 | 15fdf5f0 1684 | 7ccdbaef 1685 | f4148669 1686 | 58a6728b 1687 | 70fa55d2 1688 | f127bc90 1689 | aa2c1d76 1690 | 8aacd396 1691 | e7ad4ea6 1692 | ef2112da 1693 | 1b8a4e82 1694 | 081900cf 1695 | eee8f300 1696 | ee6a1ff5 1697 | 6b0e4223 1698 | 337a1ab9 1699 | ec344e2e 1700 | 17141151 1701 | 15c2c901 1702 | b409451f 1703 | 5da99e94 1704 | 75e93b96 1705 | 7adf5444 1706 | 1c66ddc3 1707 | de45b9ad 1708 | acab0587 1709 | 487df6fb 1710 | e703a6ae 1711 | 7972702e 1712 | 323cbd7e 1713 | d0868b68 1714 | 22d6eef2 1715 | 8ad310c4 1716 | 4021911a 1717 | cd2483a6 1718 | 37313bda 1719 | 39dec43d 1720 | 9378132a 1721 | c57bb399 1722 | af247254 1723 | d978b1c1 1724 | 05258a96 1725 | 36f751d1 1726 | b027f55a 1727 | e4ecf557 1728 | 82a08fbc 1729 | 1e645010 1730 | a46a6aeb 1731 | fc22f7c3 1732 | 444a3291 1733 | d24d2a53 1734 | 7e2897af 1735 | 8d09a0ec 1736 | 08a54ae7 1737 | 20b8d9d8 1738 | bfc19b2a 1739 | f439ab7c 1740 | f7eafced 1741 | 47100770 1742 | b01d5ff8 1743 | 9f5e46ab 1744 | 6801f93b 1745 | 1508ae94 1746 | e7a5a30a 1747 | 001b9810 1748 | 0b324c5e 1749 | a67ce96a 1750 | b0f5bd0e 1751 | 303f9d82 1752 | c116d244 1753 | e3b1a244 1754 | 9f5a9f3c 1755 | 48ae65da 1756 | b024e1de 1757 | 791dc2cd 1758 | 3d093e7a 1759 | 30366c35 1760 | 96d10820 1761 | 5384cb80 1762 | 058156f7 1763 | c77dee9a 1764 | 4b020d08 1765 | 8e2b534d 1766 | f2fb7395 1767 | 27c5ba04 1768 | b9f32077 1769 | 99f8c60d 1770 | 6ee4a5e4 1771 | b9127058 1772 | 562bbe6c 1773 | 2bbba9af 1774 | 435ebc86 1775 | 7f93e5a9 1776 | fa11c1be 1777 | 97cfc3cb 1778 | bae16111 1779 | 0ca85b09 1780 | 695da626 1781 | eec84a4c 1782 | ad5d8cc2 1783 | 50e38723 1784 | 7e5b75ca 1785 | 3e93fe02 1786 | c6f23259 1787 | 4660ba1d 1788 | 8b77e9bc 1789 | 945e7c94 1790 | bb25af99 1791 | 89de5536 1792 | 3d74670a 1793 | 7c23204f 1794 | 88baf3c8 1795 | 433e1d40 1796 | 5332036b 1797 | ace0c72c 1798 | 8f711733 1799 | f7620c9c 1800 | e5005ecc 1801 | 01c8a415 1802 | 4c842da7 1803 | 0c7e2e8b 1804 | 80c853fd 1805 | 45b0a57a 1806 | 9a901777 1807 | 9121d8bd 1808 | 869f9cd8 1809 | b6c0e1ee 1810 | 9b4c98b5 1811 | 1a7b5cc0 1812 | fb69d997 1813 | a3967172 1814 | 38d68670 1815 | 8444c323 1816 | 7bd7af94 1817 | f3470d88 1818 | dc42bf38 1819 | 11f41f08 1820 | 913e2a4b 1821 | 8779e270 1822 | 85dadf6a 1823 | d7cf53e9 1824 | 1c274406 1825 | b3fad4e6 1826 | 019b0fd8 1827 | c19af2cb 1828 | aaffb788 1829 | 8d08067b 1830 | 8de7875d 1831 | ae37de2e 1832 | c0d73182 1833 | 244e1233 1834 | ae4a847e 1835 | 8d42d233 1836 | bcd838c4 1837 | 8967340e 1838 | 76a65011 1839 | 02df411e 1840 | 19e12d21 1841 | 75b90705 1842 | ae700071 1843 | 8b61a54f 1844 | 7090e325 1845 | 90c89dbd 1846 | ea4bbafb 1847 | 139fd877 1848 | 5104c11c 1849 | d8a0b923 1850 | 8663f131 1851 | 387d7c39 1852 | 8cd65865 1853 | 177cb87f 1854 | dc81c023 1855 | 851c342f 1856 | de94f558 1857 | b54b8a3b 1858 | df301b67 1859 | 5f829719 1860 | 02075797 1861 | e0c2681b 1862 | 79ec08f4 1863 | fc3b6326 1864 | 6cc4838c 1865 | 31d2f9d7 1866 | 36530cc5 1867 | 33e4a737 1868 | 03e9343c 1869 | 08b6accb 1870 | a296dcc7 1871 | 60cf5bd4 1872 | c96541a3 1873 | dc5cb2d2 1874 | 26f39025 1875 | ba1c02f9 1876 | 6f658d17 1877 | f0ed46a0 1878 | 3bec0215 1879 | 20b98532 1880 | 75a09530 1881 | b82dcbf1 1882 | d38519b8 1883 | 45225e86 1884 | 65450f8f 1885 | bbe838d7 1886 | 6a9e2ad9 1887 | 92b283c1 1888 | f5212069 1889 | ea806eb3 1890 | c9ca4dca 1891 | a9376ce9 1892 | 35f6533e 1893 | 0c287eb4 1894 | c3c8fd67 1895 | ade6a96e 1896 | 6d987d9a 1897 | 4b9ae972 1898 | 8b4e181e 1899 | f2a43962 1900 | 12e6f61a 1901 | 13bc46e0 1902 | 089b9a73 1903 | cf3a1954 1904 | 12a65088 1905 | 2c2888a4 1906 | 3c14a8ae 1907 | b03e793e 1908 | 701c16f9 1909 | 21468c71 1910 | 3b942c6f 1911 | 33f2d0c6 1912 | 79855362 1913 | a30aeb41 1914 | 39220319 1915 | 1f398f09 1916 | bb6d4c95 1917 | 76b00e35 1918 | 2fc14f1d 1919 | 1371f82b 1920 | a16efcf7 1921 | 754f7f15 1922 | cddb1807 1923 | 0195f6be 1924 | 4197bd37 1925 | c66b40e2 1926 | f9c609b5 1927 | a9dfd1e1 1928 | c8589547 1929 | 04ecc944 1930 | 084df96a 1931 | be587af3 1932 | 9b0ed89c 1933 | f5fdfc7e 1934 | a0341168 1935 | d1f6030e 1936 | dd870bc2 1937 | 2f1a66e9 1938 | 80af8e52 1939 | 601757c4 1940 | 7de3cc42 1941 | 32e18de9 1942 | 59ded6a8 1943 | b2256412 1944 | aa91ed6a 1945 | a01166b8 1946 | b8495e71 1947 | ab120c9c 1948 | 9c9beb3b 1949 | b1bb4e76 1950 | 23016cd2 1951 | e06586a2 1952 | 994b37a0 1953 | 1419e485 1954 | 7397eec1 1955 | e1df4e90 1956 | a380e8e2 1957 | 22d49590 1958 | e6076ced 1959 | 11b34d4a 1960 | 2139b7cc 1961 | 5c966732 1962 | 24c9a406 1963 | ae284b3f 1964 | 306eb571 1965 | 35aff87c 1966 | 02ba0709 1967 | 42aa8a62 1968 | dc33a137 1969 | b2c8bc59 1970 | fa0e8c3d 1971 | fd4d13a1 1972 | 52ca8ee6 1973 | f5d34b41 1974 | 2bd2b4a6 1975 | 5ee0fbdd 1976 | 4d0b60d3 1977 | 5beaab5a 1978 | 3cc8a904 1979 | 756260cc 1980 | 88d09055 1981 | 6d05c528 1982 | 22b04a11 1983 | 7e23fab8 1984 | ca0c7a91 1985 | 5e2461cc 1986 | 050baa40 1987 | 6805c61f 1988 | 4dda3700 1989 | ede392b3 1990 | 4012ba5d 1991 | 1429d946 1992 | a90fd969 1993 | ad53adf8 1994 | bcfa5cc8 1995 | 4693aed3 1996 | 9bc0b50c 1997 | d839d12f 1998 | 066b8a25 1999 | 50a7a09d 2000 | 21bc2786 2001 | 619dce62 2002 | 71333bb4 2003 | f9439f66 2004 | f46c51c0 2005 | ec387064 2006 | 770027be 2007 | da23400a 2008 | 3c049729 2009 | 41a00630 2010 | 18c8f7da 2011 | 82a0ed9e 2012 | c4c1dc06 2013 | f394b2dd 2014 | 4372f730 2015 | e57c3b54 2016 | a46a27be 2017 | 73ec148a 2018 | 663ed3d0 2019 | df0fa87c 2020 | 36ee27ac 2021 | 8736262c 2022 | c0836644 2023 | 7fe10e9b 2024 | d9bb6853 2025 | 983be7fc 2026 | 320e2e0d 2027 | f899675e 2028 | ce8ca4d5 2029 | fbcb4f25 2030 | 23e230e5 2031 | 558203a4 2032 | 1aa3038d 2033 | f2bdd4a0 2034 | 92dc2218 2035 | b82fcb6c 2036 | 23c9143e 2037 | 3749d839 2038 | ba6cd5fe 2039 | b05774b6 2040 | 31d55faf 2041 | 33bfe5b2 2042 | 84a1835e 2043 | 9b1e522c 2044 | 7e1a7c70 2045 | 43ddbfdf 2046 | 3f6c11e4 2047 | fe41d93c 2048 | e04e25d2 2049 | --------------------------------------------------------------------------------