mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2025-01-11 15:39:29 -05:00
Support incremental builds for the bitstream.
By patching the UDS and UDI into an already built bitstream, it is now not necessary to rebuild the entire build flow when changing the UDS and the UDI. This lowers re-build times significantly. Signed-off-by: Joachim Strömbergson <joachim@assured.se>
This commit is contained in:
parent
29fd8338a7
commit
8731908cb1
@ -65,8 +65,10 @@ VERILOG_SRCS = \
|
||||
$(P)/core/timer/rtl/timer_core.v \
|
||||
$(P)/core/timer/rtl/timer.v \
|
||||
$(P)/core/uds/rtl/uds.v \
|
||||
$(P)/core/uds/rtl/uds_rom.v \
|
||||
$(P)/core/touch_sense/rtl/touch_sense.v \
|
||||
$(P)/core/tk1/rtl/tk1.v \
|
||||
$(P)/core/tk1/rtl/udi_rom.v \
|
||||
$(P)/core/uart/rtl/uart_core.v \
|
||||
$(P)/core/uart/rtl/uart_fifo.v \
|
||||
$(P)/core/uart/rtl/uart.v \
|
||||
@ -228,17 +230,18 @@ tb:
|
||||
# Main FPGA build flow.
|
||||
# Synthesis. Place & Route. Bitstream generation.
|
||||
#-------------------------------------------------------------------
|
||||
synth.json: $(FPGA_SRC) $(VERILOG_SRCS) bram_fw.hex $(P)/data/uds.hex $(P)/data/udi.hex
|
||||
synth.json: $(FPGA_SRC) $(VERILOG_SRCS) bram_fw.hex
|
||||
$(YOSYS_PATH)yosys -v3 -l synth.log -DBRAM_FW_SIZE=$(BRAM_FW_SIZE) \
|
||||
-DFIRMWARE_HEX=\"$(P)/bram_fw.hex\" \
|
||||
-DUDS_HEX=\"$(P)/data/uds.hex\" \
|
||||
-DUDI_HEX=\"$(P)/data/udi.hex\" \
|
||||
-p 'synth_ice40 -dsp -top application_fpga -json $@; write_verilog -attr2comment synth.v' \
|
||||
$(filter %.v, $^)
|
||||
|
||||
application_fpga.asc: synth.json $(P)/data/$(PIN_FILE)
|
||||
application_fpga_par.json: synth.json $(P)/data/$(PIN_FILE)
|
||||
$(NEXTPNR_PATH)nextpnr-ice40 --ignore-loops --up5k --package sg48 --json $< \
|
||||
--pcf $(P)/data/$(PIN_FILE) --asc $@
|
||||
--pcf $(P)/data/$(PIN_FILE) --write $@
|
||||
|
||||
application_fpga.asc: application_fpga_par.json $(P)/data/uds.hex $(P)/data/udi.hex
|
||||
UDS_HEX="$(P)/data/uds.hex" UDI_HEX="$(P)/data/udi.hex" OUT_ASC=$@ $(NEXTPNR_PATH)nextpnr-ice40 --up5k --package sg48 --ignore-loops --json $< --run tools/personalize.py
|
||||
|
||||
application_fpga.bin: application_fpga.asc bram_fw.hex firmware.hex
|
||||
$(ICESTORM_PATH)icebram -v bram_fw.hex firmware.hex < $< > $<.tmp
|
||||
@ -320,6 +323,7 @@ clean: clean_fw
|
||||
rm -f bram_fw.hex
|
||||
rm -f synth.{log,v,json} route.v application_fpga.{asc,bin,vcd} application_fpga_testfw.bin
|
||||
rm -f tb_application_fpga.vvp synth_tb.vvp route_tb.vvp
|
||||
rm -f application_fpga_par.json
|
||||
rm -f *.vcd
|
||||
rm -f lint_issues.txt
|
||||
rm -rf verilated
|
||||
|
@ -99,9 +99,6 @@ module tk1(
|
||||
reg [31 : 0] cdi_mem [0 : 7];
|
||||
reg cdi_mem_we;
|
||||
|
||||
reg [31 : 0] udi_mem [0 : 1];
|
||||
initial $readmemh(`UDI_HEX, udi_mem);
|
||||
|
||||
reg switch_app_reg;
|
||||
reg switch_app_we;
|
||||
|
||||
@ -156,6 +153,7 @@ module tk1(
|
||||
|
||||
reg [2 : 0] muxed_led;
|
||||
|
||||
wire [31:0] udi_rdata;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Concurrent connectivity for ports etc.
|
||||
@ -196,6 +194,12 @@ module tk1(
|
||||
/* verilator lint_on PINMISSING */
|
||||
|
||||
|
||||
udi_rom rom_i(
|
||||
.addr(address[0]),
|
||||
.data(udi_rdata)
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// reg_update
|
||||
//----------------------------------------------------------------
|
||||
@ -500,7 +504,7 @@ module tk1(
|
||||
|
||||
if ((address >= ADDR_UDI_FIRST) && (address <= ADDR_UDI_LAST)) begin
|
||||
if (!switch_app_reg) begin
|
||||
tmp_read_data = udi_mem[address[0]];
|
||||
tmp_read_data = udi_rdata;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
35
hw/application_fpga/core/tk1/rtl/udi_rom.v
Normal file
35
hw/application_fpga/core/tk1/rtl/udi_rom.v
Normal file
@ -0,0 +1,35 @@
|
||||
//======================================================================
|
||||
//
|
||||
// udi_rom.v
|
||||
// ---------
|
||||
// UDI rom generated by instatiating named SB_LUT4 resources.
|
||||
// Note: This makes the design tech specicific.
|
||||
//
|
||||
//
|
||||
// Author: Claire Xiena Wolf.
|
||||
// Copyright (C) 2023 - Tillitis AB
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
//======================================================================
|
||||
|
||||
module udi_rom (
|
||||
input wire [0:0] addr,
|
||||
output wire [31:0] data
|
||||
);
|
||||
generate
|
||||
genvar ii;
|
||||
for (ii = 0; ii < 32; ii = ii + 1'b1) begin: luts
|
||||
(* udi_rom_idx=ii, keep *) SB_LUT4
|
||||
#(
|
||||
.LUT_INIT({2'h1})
|
||||
) lut_i (
|
||||
.I0(addr[0]),
|
||||
.O(data[ii])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
||||
//======================================================================
|
||||
// EOF udi_rom.v
|
||||
//======================================================================
|
@ -36,9 +36,6 @@ module uds(
|
||||
//----------------------------------------------------------------
|
||||
// Registers including update variables and write enable.
|
||||
//----------------------------------------------------------------
|
||||
reg [31 : 0] uds_reg [0 : 7];
|
||||
initial $readmemh(`UDS_HEX, uds_reg);
|
||||
|
||||
reg uds_rd_reg [0 : 7];
|
||||
reg uds_rd_we;
|
||||
|
||||
@ -57,6 +54,17 @@ module uds(
|
||||
assign ready = tmp_ready;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// uds rom instance.
|
||||
//----------------------------------------------------------------
|
||||
uds_rom rom_i(
|
||||
.addr(address),
|
||||
.re(uds_rd_we),
|
||||
.data(tmp_read_data)
|
||||
);
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// reg_update
|
||||
//----------------------------------------------------------------
|
||||
@ -85,7 +93,6 @@ module uds(
|
||||
always @*
|
||||
begin : api
|
||||
uds_rd_we = 1'h0;
|
||||
tmp_read_data = 32'h0;
|
||||
tmp_ready = 1'h0;
|
||||
|
||||
if (cs) begin
|
||||
@ -94,14 +101,12 @@ module uds(
|
||||
if ((address >= ADDR_UDS_FIRST) && (address <= ADDR_UDS_LAST)) begin
|
||||
if (!fw_app_mode) begin
|
||||
if (uds_rd_reg[address[2 : 0]] == 1'h0) begin
|
||||
tmp_read_data = uds_reg[address[2 : 0]];
|
||||
uds_rd_we = 1'h1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule // uds
|
||||
|
||||
//======================================================================
|
||||
|
39
hw/application_fpga/core/uds/rtl/uds_rom.v
Normal file
39
hw/application_fpga/core/uds/rtl/uds_rom.v
Normal file
@ -0,0 +1,39 @@
|
||||
//======================================================================
|
||||
//
|
||||
// uds_rom.v
|
||||
// ---------
|
||||
// UDS rom. Generated by instantiating named SB_LUT4 resources.
|
||||
// Note: This makes the design technology specific.
|
||||
//
|
||||
//
|
||||
// Author: Claire Xenia Wolf
|
||||
// Copyright (C) 2023 - YosysHQ, Tillitis AB
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
//======================================================================
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module uds_rom(
|
||||
input wire [2:0] addr,
|
||||
input wire re,
|
||||
output wire [31:0] data
|
||||
);
|
||||
|
||||
generate
|
||||
genvar ii;
|
||||
for (ii = 0; ii < 32; ii = ii + 1'b1) begin: luts
|
||||
(* uds_rom_idx=ii, keep *) SB_LUT4
|
||||
#(
|
||||
.LUT_INIT({8'ha6 ^ ii[7:0], 8'h00})
|
||||
) lut_i (
|
||||
.I0(addr[0]), .I1(addr[1]), .I2(addr[2]), .I3(re),
|
||||
.O(data[ii])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
endmodule // uds_rom
|
||||
|
||||
//======================================================================
|
||||
// EOF uds_rom.v
|
||||
//======================================================================
|
63
hw/application_fpga/tools/personalize.py
Normal file
63
hw/application_fpga/tools/personalize.py
Normal file
@ -0,0 +1,63 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#=======================================================================
|
||||
#
|
||||
# personalize.py
|
||||
# --------------
|
||||
# Python program that patches the UDS and UDI implemented using
|
||||
# named LUT4 instances to have unique initial values, not the generic
|
||||
# values used during synthesis, p&r and mapping. This allows us to
|
||||
# generate device unique bitstreams without running the complete flow.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 2023 Tillitis AB
|
||||
# Written by Myrtle Shah <gatecat@ds0.me>
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
#=======================================================================
|
||||
|
||||
import os
|
||||
|
||||
def parse_hex(file, length):
|
||||
data = []
|
||||
with open(file, "r") as f:
|
||||
for line in f:
|
||||
l = line.strip()
|
||||
if len(l) > 0:
|
||||
data.append(int(l, 16))
|
||||
assert len(data) == length, len(data)
|
||||
return data
|
||||
|
||||
def rewrite_lut(lut, idx, data, has_re=False):
|
||||
# each LUT provides one bit per 32-bit word out of 64/256 bits total
|
||||
new_init = 0
|
||||
for i, word in enumerate(data):
|
||||
if (word >> idx) & 0x1:
|
||||
# repeat so inputs above address have a don't care value
|
||||
repeat = (16 // len(data))
|
||||
for k in range(repeat):
|
||||
# UDS also has a read enable
|
||||
# LUT output is zero if this isn't asserted
|
||||
if has_re and k < (repeat // 2):
|
||||
continue
|
||||
new_init |= (1 << (k * len(data) + i))
|
||||
lut.setParam("LUT_INIT", f"{new_init:016b}")
|
||||
|
||||
uds = parse_hex(os.environ["UDS_HEX"], 8)
|
||||
udi = parse_hex(os.environ["UDI_HEX"], 2)
|
||||
|
||||
uds_lut_count = 0
|
||||
udi_lut_count = 0
|
||||
|
||||
for cell_name, cell in ctx.cells:
|
||||
if "uds_rom_idx" in cell.attrs:
|
||||
index = int(cell.attrs["uds_rom_idx"], 2)
|
||||
rewrite_lut(cell, index, uds, True)
|
||||
uds_lut_count += 1
|
||||
if "udi_rom_idx" in cell.attrs:
|
||||
index = int(cell.attrs["udi_rom_idx"], 2)
|
||||
rewrite_lut(cell, index, udi, False)
|
||||
udi_lut_count += 1
|
||||
assert uds_lut_count == 32, uds_lut_count
|
||||
assert udi_lut_count == 32, udi_lut_count
|
||||
|
||||
write_bitstream(ctx, os.environ["OUT_ASC"])
|
Loading…
Reference in New Issue
Block a user