[top] First draft of reset controller integration - This PR does not implement the actual reset controller, but simply wires up the top level resets as if the controller existed - The purpose of this PR is to get agreement on the general connectivity or reset nets and ports
diff --git a/hw/Makefile b/hw/Makefile index 8277ea0..aab067a 100644 --- a/hw/Makefile +++ b/hw/Makefile
@@ -16,6 +16,14 @@ TOPS ?= top_earlgrey +# conditional flags +VERBOSE ?= 0 +toolflags ?= +ifeq ($(VERBOSE),1) + toolflags += -v +endif + + ips_reg = $(addsuffix _reg, $(IPS)) tops_gen = $(addsuffix _gen,$(TOPS)) @@ -44,8 +52,8 @@ $(eval $@_TOP := $(strip $(foreach top,$(TOPS),$(findstring $(top),$@)))) ${PRJ_DIR}/util/topgen.py -t ${PRJ_DIR}/hw/$($@_TOP)/doc/$($@_TOP).hjson \ --tpl ${PRJ_DIR}/hw/$($@_TOP)/doc/ \ - -o ${PRJ_DIR}/hw/$($@_TOP)/ + -o ${PRJ_DIR}/hw/$($@_TOP)/ ${toolflags} ${PRJ_DIR}/util/topgen.py -t ${PRJ_DIR}/hw/$($@_TOP)/doc/$($@_TOP).hjson \ - -r -o ${PRJ_DIR}/hw/$($@_TOP)/dv/env/ + -r -o ${PRJ_DIR}/hw/$($@_TOP)/dv/env/ ${toolflags} .PHONY: all $(ips_reg) $(tops_gen)
diff --git a/hw/top_earlgrey/doc/top_earlgrey.gen.hjson b/hw/top_earlgrey/doc/top_earlgrey.gen.hjson index b31b81c..37dd6af 100644 --- a/hw/top_earlgrey/doc/top_earlgrey.gen.hjson +++ b/hw/top_earlgrey/doc/top_earlgrey.gen.hjson
@@ -16,6 +16,25 @@ freq: "100000000" } ] + resets: + [ + { + name: lc + type: root + clk: main + } + { + name: sys + type: root + clk: main + } + { + name: spi_device + type: leaf + root: sys + clk: main + } + ] num_cores: "1" module: [ @@ -23,6 +42,10 @@ name: uart type: uart clock: main + reset_connections: + { + rst_ni: sys + } base_addr: 0x40000000 size: 0x1000 ip_clock: main @@ -94,6 +117,10 @@ name: gpio type: gpio clock: main + reset_connections: + { + rst_ni: sys + } base_addr: 0x40010000 size: 0x1000 ip_clock: main @@ -123,6 +150,10 @@ name: spi_device type: spi_device clock: main + reset_connections: + { + rst_ni: spi_device + } base_addr: 0x40020000 size: 0x1000 ip_clock: main @@ -194,6 +225,10 @@ name: flash_ctrl type: flash_ctrl clock: main + reset_connections: + { + rst_ni: lc + } base_addr: 0x40030000 size: 0x1000 ip_clock: main @@ -241,6 +276,10 @@ name: rv_timer type: rv_timer clock: main + reset_connections: + { + rst_ni: sys + } base_addr: 0x40080000 size: 0x1000 ip_clock: main @@ -263,6 +302,10 @@ name: hmac type: hmac clock: main + reset_connections: + { + rst_ni: sys + } base_addr: 0x40120000 size: 0x1000 ip_clock: main @@ -290,6 +333,10 @@ name: rv_plic type: rv_plic clock: main + reset_connections: + { + rst_ni: sys + } base_addr: 0x40090000 generated: "true" parameter: @@ -311,18 +358,30 @@ [ { name: rom + reset_connections: + { + rst_ni: sys + } type: rom base_addr: 0x00008000 size: 0x2000 } { name: ram_main + reset_connections: + { + rst_ni: sys + } type: ram_1p base_addr: 0x10000000 size: 0x10000 } { name: eflash + reset_connections: + { + rst_ni: lc + } type: eflash base_addr: 0x20000000 size: 0x80000 @@ -333,6 +392,11 @@ { name: main clock: main + reset: sys + reset_connections: + { + rst_main_ni: sys + } connections: { corei:
diff --git a/hw/top_earlgrey/doc/top_earlgrey.hjson b/hw/top_earlgrey/doc/top_earlgrey.hjson index 9a56d44..281455b 100644 --- a/hw/top_earlgrey/doc/top_earlgrey.hjson +++ b/hw/top_earlgrey/doc/top_earlgrey.hjson
@@ -12,6 +12,17 @@ { name: "main", freq: "100000000" } ] + // Reset attributes + // name: name of reset. Real name is `name`_rst_n + // type: reset type, either root or leaf + // root: if reset type not root, the root reset it is related to + // clk: related clock domain for synchronous release + resets: [ + { name: "lc", type: "root", clk: "main"} + { name: "sys", type: "root", clk: "main"} + { name: "spi_device", type: "leaf", root: "sys", clk: "main"} + ] + // Number of cores: used in rv_plic and timer num_cores: "1", @@ -22,39 +33,50 @@ { name: "uart", // instance name type: "uart", // Must be matched to the ip name in `ip.hson` (_reg, _cfg permitted) // and `hw/ip/{type}` + clock: "main", // `ip.hjson` clock is internal name, here top determines // actual clock (signal matched at the top) + + // reset connections defines the port to top level reset connection + // the ip.hjson will declare the reset port names + reset_connections: {rst_ni: "sys"}, base_addr: "0x40000000", }, { name: "gpio", type: "gpio", clock: "main", + reset_connections: {rst_ni: "sys"}, base_addr: "0x40010000", } { name: "spi_device", type: "spi_device", clock: "main", + reset_connections: {rst_ni: "spi_device"}, base_addr: "0x40020000", }, { name: "flash_ctrl", type: "flash_ctrl", clock: "main", + reset_connections: {rst_ni: "lc"}, base_addr: "0x40030000", }, { name: "rv_timer", type: "rv_timer", clock: "main", + reset_connections: {rst_ni: "sys"}, base_addr: "0x40080000", }, { name: "hmac", type: "hmac", clock: "main", + reset_connections: {rst_ni: "sys"}, base_addr: "0x40120000", }, { name: "rv_plic", type: "rv_plic", clock: "main", + reset_connections: {rst_ni: "sys"}, base_addr: "0x40090000", generated: "true" // Indicate this module is generated in the topgen parameter: { @@ -68,9 +90,9 @@ // Memories (ROM, RAM, eFlash) are defined at the top. // It utilizes the primitive cells but configurable memory: [ - { name: "rom", type: "rom", base_addr: "0x00008000", size: "0x2000" }, - { name: "ram_main", type: "ram_1p", base_addr: "0x10000000", size: "0x10000" }, - { name: "eflash", type: "eflash", base_addr: "0x20000000", size: "0x80000" }, + { name: "rom", reset_connections: {rst_ni: "sys"}, type: "rom", base_addr: "0x00008000", size: "0x2000" }, + { name: "ram_main", reset_connections: {rst_ni: "sys"}, type: "ram_1p", base_addr: "0x10000000", size: "0x10000" }, + { name: "eflash", reset_connections: {rst_ni: "lc"}, type: "eflash", base_addr: "0x20000000", size: "0x80000" }, ], debug_mem_base_addr: "0x1A110000", @@ -81,6 +103,8 @@ xbar: [ { name: "main", clock: "main", // Main clock, used in sockets + reset: "sys", + reset_connections: {rst_main_ni: "sys"} }, ],
diff --git a/hw/top_earlgrey/doc/top_earlgrey.tpl.sv b/hw/top_earlgrey/doc/top_earlgrey.tpl.sv index d2bc994..8ce39f8 100644 --- a/hw/top_earlgrey/doc/top_earlgrey.tpl.sv +++ b/hw/top_earlgrey/doc/top_earlgrey.tpl.sv
@@ -76,6 +76,12 @@ tl_h2d_t tl_${m["name"]}_d_h2d; tl_d2h_t tl_${m["name"]}_d_d2h; % endfor + + //reset wires declaration +% for reset in top['resets']: + logic ${reset['name']}_rst_n; +% endfor + <% interrupt_num = sum([x["width"] if "width" in x else 1 for x in top["interrupt"]]) %>\ @@ -96,12 +102,24 @@ logic [${(interrupt_num).bit_length()-1}:0] irq_id[1]; logic [0:0] msip; - // Non-debug module reset == reset for everything except for the debug module - // and the logic required to access it. - logic ndmreset_n; - logic ndmreset_from_dm; - assign ndmreset_n = (scanmode_i) ? rst_ni : ~ndmreset_from_dm & rst_ni; + // Non-debug module reset == reset for everything except for the debug module + logic ndmreset_req; + + // root resets + // TODO: lc_rst_n is not the true root reset. It will be differentiated once the + // the reset controller logic is present + assign lc_rst_n = rst_ni; + assign sys_rst_n = (scanmode_i) ? lc_rst_n : ~ndmreset_req & lc_rst_n; + + //non-root reset assignments +% for reset in top['resets']: + % if reset['type'] in ['leaf']: + assign ${reset['name']}_rst_n = ${reset['root']}_rst_n; + % endif +% endfor + + // debug request from rv_dm to core logic debug_req; // processor core @@ -116,7 +134,7 @@ ) core ( // clock and reset .clk_i (clk_i), - .rst_ni (ndmreset_n), + .rst_ni (sys_rst_n), .test_en_i (1'b0), // static pinning .hart_id_i (32'b0), @@ -151,9 +169,9 @@ // 1 required by standard ) u_dm_top ( .clk_i (clk_i), - .rst_ni (rst_ni), + .rst_ni (lc_rst_n), .testmode_i (1'b0), - .ndmreset_o (ndmreset_from_dm), + .ndmreset_o (ndmreset_req), .dmactive_o (), .debug_req_o (debug_req), .unavailable_i (1'b0), @@ -177,12 +195,16 @@ ## Memory Instantiation % for m in top["memory"]: +<% + resets = m['reset_connections'] +%>\ % if m["type"] == "ram_1p": <% data_width = int(top["datawidth"]) dw_byte = data_width // 8 addr_width = ((int(m["size"], 0) // dw_byte) -1).bit_length() sram_depth = (int(m["size"], 0) // dw_byte) + %>\ // sram device logic ${m["name"]}_req; @@ -199,8 +221,9 @@ .Outstanding(1) ) tl_adapter_${m["name"]} ( .clk_i, - .rst_ni (ndmreset_n), - + % for key in resets: + .${key} (${resets[key]}_rst_n), + % endfor .tl_i (tl_${m["name"]}_d_h2d), .tl_o (tl_${m["name"]}_d_d2h), @@ -222,7 +245,9 @@ .DataBitsPerMask(${int(data_width/4)}) ) u_ram1p_${m["name"]} ( .clk_i, - .rst_ni (ndmreset_n), + % for key in resets: + .${key} (${resets[key]}_rst_n), + % endfor .req_i (${m["name"]}_req), .write_i (${m["name"]}_we), @@ -252,7 +277,9 @@ .ErrOnWrite(1) ) tl_adapter_${m["name"]} ( .clk_i, - .rst_ni (ndmreset_n), + % for key in resets: + .${key} (${resets[key]}_rst_n), + % endfor .tl_i (tl_${m["name"]}_d_h2d), .tl_o (tl_${m["name"]}_d_d2h), @@ -274,7 +301,9 @@ .Depth(${rom_depth}) ) u_rom_${m["name"]} ( .clk_i, - .rst_ni (ndmreset_n), + % for key in resets: + .${key} (${resets[key]}_rst_n), + % endfor .cs_i (${m["name"]}_req), .addr_i (${m["name"]}_addr), .dout_o (${m["name"]}_rdata), @@ -302,7 +331,9 @@ .ErrOnWrite(1) ) tl_adapter_${m["name"]} ( .clk_i, - .rst_ni (ndmreset_n), + % for key in resets: + .${key} (${resets[key]}_rst_n), + % endfor .tl_i (tl_${m["name"]}_d_h2d), .tl_o (tl_${m["name"]}_d_d2h), @@ -325,7 +356,9 @@ .DataWidth(${data_width}) ) u_flash_${m["name"]} ( .clk_i, - .rst_ni, + % for key in resets: + .${key} (${resets[key]}_rst_n), + % endfor .host_req_i (flash_host_req), .host_addr_i (flash_host_addr), .host_req_rdy_o (flash_host_req_rdy), @@ -339,9 +372,12 @@ // flash memory is embedded within controller % endif % endfor - ## Peripheral Instantiation + % for m in top["module"]: +<% + +%>\ % if "parameter" in m: ${m["type"]} #( % for k, v in m["parameter"].items(): @@ -389,11 +425,18 @@ .irq_id_o (irq_id), .msip_o (msip), % endif + % if m["scan"] == "true": .scanmode_i (scanmode_i), % endif - .clk_i(${"clk_i" if m["clock"] == "main" else "clk_"+ m["clock"] + "_i"}), - .rst_ni(${"ndmreset_n" if m["clock"] == "main" else "rst_" + m["clock"] + "_ni"}) + .clk_i (${"clk_i" if m["clock"] == "main" else "clk_"+ m["clock"] + "_i"}), + % for k, v in m["reset_connections"].items(): + % if loop.last: + .${k} (${v}_rst_n) + % else: + .${k} (${v}_rst_n), + % endif + % endfor ); % endfor @@ -410,10 +453,8 @@ // TL-UL Crossbar logic clk_main; - logic ndmreset_sync_main_n; // ndmreset synchronized to clk_main - assign clk_main = clk_i; - assign ndmreset_sync_main_n = ndmreset_n; + % for xbar in top["xbar"]: <% @@ -421,11 +462,11 @@ %>\ xbar_${xbar["name"]} u_xbar_${xbar["name"]} ( % for clock in xbar["clocks"]: - ## TODO: How we can handle the reset? .clk_${clock}_i (clk_${clock}), - .rst_${clock}_ni (ndmreset_sync_${clock}_n), % endfor - + % for k, v in xbar["reset_connections"].items(): + .${k} (${v}_rst_n), + % endfor % for node in xbar["nodes"]: % if node["type"] == "device": .tl_${(node["name"]+"_o").ljust(name_len+2)} (tl_${node["name"]}_d_h2d),
diff --git a/hw/top_earlgrey/doc/xbar_main.hjson b/hw/top_earlgrey/doc/xbar_main.hjson index 6694c7c..2c49d87 100644 --- a/hw/top_earlgrey/doc/xbar_main.hjson +++ b/hw/top_earlgrey/doc/xbar_main.hjson
@@ -1,6 +1,7 @@ { name: "main", type: "xbar", clock: "main", // Main clock, used in sockets + reset_primary: "rst_main_ni", // Main reset, used in sockets nodes: [ { name: "corei", type: "host",
diff --git a/hw/top_earlgrey/ip/xbar/doc/xbar_main.gen.hjson b/hw/top_earlgrey/ip/xbar/doc/xbar_main.gen.hjson index ee7e552..c246a2b 100644 --- a/hw/top_earlgrey/ip/xbar/doc/xbar_main.gen.hjson +++ b/hw/top_earlgrey/ip/xbar/doc/xbar_main.gen.hjson
@@ -9,6 +9,11 @@ { name: main clock: main + reset: sys + reset_connections: + { + rst_main_ni: sys + } connections: { corei:
diff --git a/hw/top_earlgrey/rtl/top_earlgrey.sv b/hw/top_earlgrey/rtl/top_earlgrey.sv index d18e26f..5e46916 100644 --- a/hw/top_earlgrey/rtl/top_earlgrey.sv +++ b/hw/top_earlgrey/rtl/top_earlgrey.sv
@@ -76,6 +76,12 @@ tl_d2h_t tl_ram_main_d_d2h; tl_h2d_t tl_eflash_d_h2d; tl_d2h_t tl_eflash_d_d2h; + + //reset wires declaration + logic lc_rst_n; + logic sys_rst_n; + logic spi_device_rst_n; + logic [53:0] intr_vector; // Interrupt source list logic intr_uart_tx_watermark; @@ -108,12 +114,20 @@ logic [5:0] irq_id[1]; logic [0:0] msip; - // Non-debug module reset == reset for everything except for the debug module - // and the logic required to access it. - logic ndmreset_n; - logic ndmreset_from_dm; - assign ndmreset_n = (scanmode_i) ? rst_ni : ~ndmreset_from_dm & rst_ni; + // Non-debug module reset == reset for everything except for the debug module + logic ndmreset_req; + + // root resets + // TODO: lc_rst_n is not the true root reset. It will be differentiated once the + // the reset controller logic is present + assign lc_rst_n = rst_ni; + assign sys_rst_n = (scanmode_i) ? lc_rst_n : ~ndmreset_req & lc_rst_n; + + //non-root reset assignments + assign spi_device_rst_n = sys_rst_n; + + // debug request from rv_dm to core logic debug_req; // processor core @@ -128,7 +142,7 @@ ) core ( // clock and reset .clk_i (clk_i), - .rst_ni (ndmreset_n), + .rst_ni (sys_rst_n), .test_en_i (1'b0), // static pinning .hart_id_i (32'b0), @@ -163,9 +177,9 @@ // 1 required by standard ) u_dm_top ( .clk_i (clk_i), - .rst_ni (rst_ni), + .rst_ni (lc_rst_n), .testmode_i (1'b0), - .ndmreset_o (ndmreset_from_dm), + .ndmreset_o (ndmreset_req), .dmactive_o (), .debug_req_o (debug_req), .unavailable_i (1'b0), @@ -200,7 +214,7 @@ .ErrOnWrite(1) ) tl_adapter_rom ( .clk_i, - .rst_ni (ndmreset_n), + .rst_ni (sys_rst_n), .tl_i (tl_rom_d_h2d), .tl_o (tl_rom_d_d2h), @@ -221,7 +235,7 @@ .Depth(2048) ) u_rom_rom ( .clk_i, - .rst_ni (ndmreset_n), + .rst_ni (sys_rst_n), .cs_i (rom_req), .addr_i (rom_addr), .dout_o (rom_rdata), @@ -243,8 +257,7 @@ .Outstanding(1) ) tl_adapter_ram_main ( .clk_i, - .rst_ni (ndmreset_n), - + .rst_ni (sys_rst_n), .tl_i (tl_ram_main_d_h2d), .tl_o (tl_ram_main_d_d2h), @@ -265,7 +278,7 @@ .DataBitsPerMask(8) ) u_ram1p_ram_main ( .clk_i, - .rst_ni (ndmreset_n), + .rst_ni (sys_rst_n), .req_i (ram_main_req), .write_i (ram_main_we), @@ -295,7 +308,7 @@ .ErrOnWrite(1) ) tl_adapter_eflash ( .clk_i, - .rst_ni (ndmreset_n), + .rst_ni (lc_rst_n), .tl_i (tl_eflash_d_h2d), .tl_o (tl_eflash_d_d2h), @@ -318,7 +331,7 @@ .DataWidth(32) ) u_flash_eflash ( .clk_i, - .rst_ni, + .rst_ni (lc_rst_n), .host_req_i (flash_host_req), .host_addr_i (flash_host_addr), .host_req_rdy_o (flash_host_req_rdy), @@ -343,8 +356,9 @@ .intr_rx_break_err_o (intr_uart_rx_break_err), .intr_rx_timeout_o (intr_uart_rx_timeout), .intr_rx_parity_err_o (intr_uart_rx_parity_err), - .clk_i(clk_i), - .rst_ni(ndmreset_n) + + .clk_i (clk_i), + .rst_ni (sys_rst_n) ); gpio gpio ( @@ -354,8 +368,9 @@ .cio_gpio_o (cio_gpio_gpio_d2p_o), .cio_gpio_en_o (cio_gpio_gpio_en_d2p_o), .intr_gpio_o (intr_gpio_gpio), - .clk_i(clk_i), - .rst_ni(ndmreset_n) + + .clk_i (clk_i), + .rst_ni (sys_rst_n) ); spi_device spi_device ( @@ -372,9 +387,10 @@ .intr_rxerr_o (intr_spi_device_rxerr), .intr_rxoverflow_o (intr_spi_device_rxoverflow), .intr_txunderflow_o (intr_spi_device_txunderflow), + .scanmode_i (scanmode_i), - .clk_i(clk_i), - .rst_ni(ndmreset_n) + .clk_i (clk_i), + .rst_ni (spi_device_rst_n) ); flash_ctrl flash_ctrl ( @@ -388,16 +404,18 @@ .intr_op_error_o (intr_flash_ctrl_op_error), .flash_o(flash_c2m), .flash_i(flash_m2c), - .clk_i(clk_i), - .rst_ni(ndmreset_n) + + .clk_i (clk_i), + .rst_ni (lc_rst_n) ); rv_timer rv_timer ( .tl_i (tl_rv_timer_d_h2d), .tl_o (tl_rv_timer_d_d2h), .intr_timer_expired_0_0_o (intr_rv_timer_timer_expired_0_0), - .clk_i(clk_i), - .rst_ni(ndmreset_n) + + .clk_i (clk_i), + .rst_ni (sys_rst_n) ); hmac hmac ( @@ -405,8 +423,9 @@ .tl_o (tl_hmac_d_d2h), .intr_hmac_done_o (intr_hmac_hmac_done), .intr_fifo_full_o (intr_hmac_fifo_full), - .clk_i(clk_i), - .rst_ni(ndmreset_n) + + .clk_i (clk_i), + .rst_ni (sys_rst_n) ); rv_plic #( @@ -418,8 +437,9 @@ .irq_o (irq_plic), .irq_id_o (irq_id), .msip_o (msip), - .clk_i(clk_i), - .rst_ni(ndmreset_n) + + .clk_i (clk_i), + .rst_ni (sys_rst_n) ); // interrupt assignments @@ -451,15 +471,12 @@ // TL-UL Crossbar logic clk_main; - logic ndmreset_sync_main_n; // ndmreset synchronized to clk_main - assign clk_main = clk_i; - assign ndmreset_sync_main_n = ndmreset_n; + xbar_main u_xbar_main ( .clk_main_i (clk_main), - .rst_main_ni (ndmreset_sync_main_n), - + .rst_main_ni (sys_rst_n), .tl_corei_i (tl_corei_h_h2d), .tl_corei_o (tl_corei_h_d2h), .tl_cored_i (tl_cored_h_h2d),
diff --git a/util/tlgen/elaborate.py b/util/tlgen/elaborate.py index 55ab994..31e0f2d 100644 --- a/util/tlgen/elaborate.py +++ b/util/tlgen/elaborate.py
@@ -29,7 +29,7 @@ ## Build address map ## Each socket_1n should have address map - ## Gather clocks + ## Gather clocks and resets xbar.clocks = {xbar.clock } | {clk for node in xbar.nodes for clk in node.clocks}
diff --git a/util/tlgen/item.py b/util/tlgen/item.py index b26b54e..6c40360 100644 --- a/util/tlgen/item.py +++ b/util/tlgen/item.py
@@ -44,6 +44,7 @@ clocks = [] # Clocks # Clock domain of the node # e.g. async_fifo in : clk_core , out : clk_main + # If NodeType is Socket out from 1:N then address steering is used # But this value is also propagated up to a Host from multiple Devices # Device Node should have address_from, address_to
diff --git a/util/tlgen/xbar.py b/util/tlgen/xbar.py index 04dc39f..8dfae7a 100644 --- a/util/tlgen/xbar.py +++ b/util/tlgen/xbar.py
@@ -20,6 +20,7 @@ clock = "" # str # Main clock remove 'clk_' prefix name = "" # str # e.g. "main" --> main_xbar clocks = [] # Clocks + # prefix is useful if SoC has more than one Xbar # variables after elaboration. Shouldn't be touched by outside
diff --git a/util/topgen.py b/util/topgen.py index 0431c66..388c2b0 100755 --- a/util/topgen.py +++ b/util/topgen.py
@@ -58,7 +58,7 @@ if not tlgen.elaborate(xbar): log.error("Elaboration failed." + repr(xbar)) - # Add clocks to the top configuration + # Add clocks/resets to the top configuration obj["clocks"] = xbar.clocks try: out_rtl, out_pkg, out_bind = tlgen.generate(xbar) @@ -347,7 +347,7 @@ (", ".join([x["name"] for x in xbar_objs]))) # TODO: Add validate - topcfg, error = validate_top(topcfg) + topcfg, error = validate_top(topcfg, ip_objs, xbar_objs) if error != 0: raise SystemExit("Error occured while validating top.hjson")
diff --git a/util/topgen/validate.py b/util/topgen/validate.py index 4f45aba..3f1e1a4 100644 --- a/util/topgen/validate.py +++ b/util/topgen/validate.py
@@ -1,7 +1,6 @@ # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 - import logging as log from reggen.validate import val_types, check_keys @@ -84,8 +83,101 @@ def check_pinmux(top, prefix): return 0 +def check_resets(top, ipobjs, xbarobjs): + # all defined reset nets + reset_nets = [reset['name'] for reset in top['resets']] + error = 0 -def validate_top(top): + # Check reset port connection for all IPs + for ipcfg in top['module']: + log.info("Checking resets for %s" % ipcfg['name'].lower()) + ipdef = [ip for ip in ipobjs if ipcfg['type'] == ip['name'].lower()] + error += check_rst_def(ipdef, ipcfg['type']) + error += validate_reset(ipcfg, ipdef[0], reset_nets) + + if error: + log.error("module reset checking failed") + break + + # Check reset port connection for all xbars + for xbarcfg in top['xbar']: + log.info("Checking resets for %s" % xbarcfg['name'].lower()) + xbardef = [ + xbar for xbar in xbarobjs + if xbarcfg['name'] == xbar['name'].lower() + ] + error += check_rst_def(xbardef, xbarcfg['name']) + error += validate_reset(xbarcfg, xbardef[0], reset_nets, "xbar") + + if error: + log.error("xbar reset checking failed") + break + + return error + +def check_rst_def(inst_def, name): + error = 0 + if not inst_def: + log.error("Could not find %s.hjson for" % name) + error += 1 + + if len(inst_def) > 1: + log.error("Duplicate %s.hjson" % name) + error += 1 + + return error + +# Checks the following +# For each defined reset connection in top*.hjson, there exists a defined port at the destination +# and defined reset net +# There are the same number of defined connections as there are ports +def validate_reset(top, inst, reset_nets, prefix=""): + # Gather inst port list + error = 0 + inst_port_list = [] + if 'reset_primary' not in inst.keys(): + log.info("%s %s does not have a reset_primary defined, default used" % + (prefix, inst['name'])) + inst_port_list.append("rst_ni") + else: + inst_port_list.append(inst['reset_primary']) + + if 'other_reset_list' in inst.keys(): + inst_port_list.extend(inst['other_reset_list']) + log.info("%s %s resets are %s" % + (prefix, inst['name'].lower(), inst_port_list)) + + if len(top['reset_connections'].keys()) != len(inst_port_list): + error += 1 + log.error("%s %s mismatched number of ports and nets" % + (prefix, inst['name'])) + + missing_port = [ + port for port in top['reset_connections'].keys() + if port not in inst_port_list + ] + + if missing_port: + error += 1 + log.error("%s %s Following reset ports do not exist:" % + (prefix, inst['name'])) + [log.error("%s" % port) for port in missing_port] + + missing_net = [ + net for port, net in top['reset_connections'].items() + if net not in reset_nets + ] + + if missing_net: + error += 1 + log.error("%s %s Following reset nets do not exist:" % + (prefix, inst['name'])) + [log.error("%s" % net) for net in missing_net] + + return error + + +def validate_top(top, ipobjs, xbarobjs): # return as it is for now error = check_keys(top, top_required, top_optional, top_added, "top") @@ -95,6 +187,9 @@ component = top['name'] + ## Reset check + error += check_resets(top, ipobjs, xbarobjs) + ## MODULE check ## MEMORY check