├── 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 | [](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 |
--------------------------------------------------------------------------------