From 1dd942bbfc9909034ceed8a277fb82bbae00e5c7 Mon Sep 17 00:00:00 2001 From: aottaviano Date: Sat, 22 Jun 2024 17:04:25 +0200 Subject: [PATCH 1/2] src: Add support for Kairos --- src/dumpling/CLIEntryPoint.py | 2 + src/dumpling/Chips/Kairos.py | 755 ++++++++++++++++++++++++++++++++++ 2 files changed, 757 insertions(+) create mode 100644 src/dumpling/Chips/Kairos.py diff --git a/src/dumpling/CLIEntryPoint.py b/src/dumpling/CLIEntryPoint.py index b8a10fc..8552a25 100644 --- a/src/dumpling/CLIEntryPoint.py +++ b/src/dumpling/CLIEntryPoint.py @@ -21,6 +21,7 @@ from dumpling.Chips import Siracusa from dumpling.Chips import Trikarenos from dumpling.Chips import Cerberus +from dumpling.Chips import Kairos _CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"]) @@ -38,6 +39,7 @@ def cli(*args) -> None: cli.add_command(Siracusa.siracusa) cli.add_command(Trikarenos.trikarenos) cli.add_command(Cerberus.cerberus) +cli.add_command(Kairos.kairos) # For debugging purposes only if __name__ == "__main__": diff --git a/src/dumpling/Chips/Kairos.py b/src/dumpling/Chips/Kairos.py new file mode 100644 index 0000000..a2bda02 --- /dev/null +++ b/src/dumpling/Chips/Kairos.py @@ -0,0 +1,755 @@ +# Alessandro Ottaviano +# +# Copyright (C) 2024 ETH Zürich +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import math +import re +from pathlib import Path +from collections import namedtuple +from typing import Mapping + +import bitstring +import click +from dumpling.Common.ElfParser import ElfParser +from bitstring import BitArray + +bitstring.lsb0 = True # Enables the experimental mode to index LSB with 0 instead of the MSB (see thread https://github.com/scott-griffiths/bitstring/issues/156) +from dumpling.Common.HP93000 import HP93000VectorWriter +from dumpling.JTAGTaps.PulpJTAGTap import PULPJtagTap +from dumpling.Common.VectorBuilder import PinDecl, VectorBuilder +from dumpling.Drivers.JTAG import JTAGDriver +from dumpling.JTAGTaps.RISCVDebugTap import RISCVDebugTap, RISCVReg + +# Pin Setup + +pins: Mapping[str, PinDecl] = { + "chip_reset": {"name": "pad_rst_n", "default": "1", "type": "input"}, + "trst": {"name": "pad_jtag_trstn", "default": "1", "type": "input"}, + "tms": {"name": "pad_jtag_tms", "default": "0", "type": "input"}, + "tck": {"name": "pad_jtag_tck", "default": "0", "type": "input"}, + "tdi": {"name": "pad_jtag_tdi", "default": "0", "type": "input"}, + "tdo": {"name": "pad_jtag_tdo", "default": "X", "type": "output"}, +} + +FC_CORE_ID: BitArray = BitArray("0x003e0") # type: ignore until https://github.com/scott-griffiths/bitstring/issues/276 is closed + +# GPIO Functional Modes? + +# Minimal setup +vector_builder = VectorBuilder(pins) +jtag_driver = JTAGDriver(vector_builder) + +# Instantiate the two JTAG taps in Kairos PULPissimo +riscv_debug_tap = RISCVDebugTap(jtag_driver, "0x2f33ddb3") +pulp_tap = PULPJtagTap(jtag_driver, "0x20cc2db3") +# Add the taps to the jtag chain in the right order +jtag_driver.add_tap(riscv_debug_tap) +jtag_driver.add_tap(pulp_tap) + +# Commands +pass_VectorWriter = click.make_pass_decorator(HP93000VectorWriter) + + +# Entry point for all kairos related commands +@click.group() +@click.option( + "--port-name", "-p", type=str, default="jtag_and_reset_port", show_default=True +) +@click.option("--wtb-name", "-w", type=str, default="multiport", show_default=True) +@click.option( + "--output", + "-o", + type=click.Path(exists=False, file_okay=True, writable=True), + default="vectors.avc", + show_default=True, +) +@click.option( + "--device_cycle_name", + "-d", + type=str, + default="dvc_1", +) +@click.pass_context +def kairos(ctx, port_name, wtb_name, device_cycle_name, output): + """Generate stimuli for the TSMC65 Kairos chip.""" + # Instantiate the vector writer and attach it to the command context so subcommands can access it. + vector_builder.init() + ctx.obj = HP93000VectorWriter( + stimuli_file_path=Path(output), + pins=pins, + port=port_name, + device_cycle_name=device_cycle_name, + wtb_name=wtb_name, + ) + + +@kairos.command() +@click.option( + "--elf", + "-e", + required=True, + type=click.Path(exists=True, file_okay=True, dir_okay=False), + help="The path to the elf binary to preload.", +) +@click.option( + "--return-code", + "-r", + type=click.IntRange(min=0, max=255), + help="Set a return code to check against during end of computation detection. A matched loop will be inserted to achieve ", +) +@click.option( + "--eoc-wait-cycles", + "-w", + default=6, + type=click.IntRange(min=0), + help="If set to a non zero integer, wait the given number of cycles for end of computation check and bdon't use ", +) +@click.option( + "--verify/--no-verify", + default=True, + help="Enables/Disables verifying the content written to L2.", + show_default=True, +) +@click.option( + "--compress", + "-c", + is_flag=True, + default=False, + show_default=True, + help="Compress all vectors by merging subsequent identical vectors into a single vector with increased repeat value.", +) +@click.option( + "--no-reset", + is_flag=True, + default=False, + show_default=True, + help="Don't reset the chip before executing the binary. Helpfull for debugging and to keep custom config preloaded via " + "JTAG.", +) + +@click.option( + "--no-resume", + is_flag=True, + default=False, + show_default=True, + help="Don't resume the core." +) + +@pass_VectorWriter +def execute_elf( + writer: HP93000VectorWriter, + elf, + return_code, + eoc_wait_cycles, + verify, + compress, + no_reset, + no_resume +): + """Generate vectors to load and execute the given elf binary. + + The command parses the binary supplied with the '--elf' parameter and + writes the generated stimuli to the given OUTPUT file. Additionally to the + AVC ASCII output, a .wtb and .tmf with identical basename is created. The + vectors take care of resetting the chip, halting the core, preloading the + binary into L2 memory with optional verification and resuming the core. If + an expected return code is supplied with the optional '--return-code' flag, + either a matched loop (polling) check or a single check (after a + configurable number of idle clock cycles) for end of computation is added + to the end of the stimuli vectors depending on the value of + --eoc-wait-cycles. + + """ + + with writer as vector_writer: + vectors = [] + if not no_reset: + # Assert reset + vector_builder.chip_reset = 0 + # Wait 1us + reset_vector = vector_builder.vector(comment="Assert reset") + vectors.append(vector_builder.loop([reset_vector], 10)) + # Write the vectors to disk + vector_writer.write_vectors(vectors, compress=compress) + + # Reset the jtag interface and wait for 10 cycles + vectors = jtag_driver.jtag_reset() + vectors += jtag_driver.jtag_idle_vectors(10) + vector_writer.write_vectors(vectors, compress=compress) + + #vectors += jtag_driver.jtag_idle_vectors(10) + #vector_builder.chip_reset = 1 + #vectors += [vector_builder.vector(comment="Release hard reset")] + #vector_writer.write_vectors(vectors, compress=compress) + + ## Start boot procedure + ## Halt fabric controller + #vectors = riscv_debug_tap.init_dmi() + #vectors += riscv_debug_tap.set_dmactive(True) + #vectors += riscv_debug_tap.halt_hart_no_loop(FC_CORE_ID, wait_cycles=100) + + #vector_writer.write_vectors(vectors, compress=compress) + + # Write the boot address into dpc + parser = ElfParser() + parser.add_binary(elf) + entry_address = BitArray(int=parser.get_entry(), length=32) + vectors = riscv_debug_tap.write_reg_abstract_cmd_no_loop( + RISCVReg.CSR_DPC, + BitArray(entry_address), # type: ignore until https://github.com/scott-griffiths/bitstring/issues/276 is closed + comment="Writing boot address to DPC", + ) + vector_writer.write_vectors(vectors, compress=compress) + + # Verify boot address + vectors = riscv_debug_tap.read_reg_abstract_cmd_no_loop( + RISCVReg.CSR_DPC, + BitArray(entry_address).bin, + wait_cycles=10, + comment="Reading DPC", + ) + vector_writer.write_vectors(vectors, compress=compress) + + # Load L2 memory + vectors = pulp_tap.init_pulp_tap() + vectors += pulp_tap.loadL2(elf_binary=elf) + vector_writer.write_vectors(vectors, compress=compress) + + # Optionally verify the data we just wrote to L2 + if verify: + vectors = pulp_tap.verifyL2_no_loop( + elf, + wait_cycles=eoc_wait_cycles, + comment="Verify the content of L2 to match the binary.", + ) + vector_writer.write_vectors(vectors, compress=compress) + + if not no_resume: + # Resume core + vectors = riscv_debug_tap.init_dmi() # Change JTAG IR to DMIACCESS + vectors += riscv_debug_tap.resume_harts(FC_CORE_ID,"Resuming core", retries=16) +# vectors += riscv_debug_tap.resume_harts_no_loop(FC_CORE_ID, wait_cycles=100) + vector_writer.write_vectors(vectors, compress=compress) + + # Wait for end of computation by polling EOC register address + if return_code != None: + if eoc_wait_cycles <= 0: + vectors = riscv_debug_tap.wait_for_end_of_computation( + return_code, idle_vector_count=100, max_retries=10 + ) + else: + vectors = [ + jtag_driver.jtag_idle_vector( + repeat=eoc_wait_cycles, + comment="Waiting for computation to finish before checking EOC register.", + ) + ] + vectors += riscv_debug_tap.check_end_of_computation( + return_code, wait_cycles=5000 + ) + vector_writer.write_vectors(vectors, compress=compress) + + +@kairos.command() +@click.argument("address_value_mappings", nargs=-1) +@click.option( + "--verify/--no-verify", + default=True, + help="Enables/Disables verifying the content written to L2.", + show_default=True, +) +@click.option( + "--loop/--no-loop", + default=False, + help="If true, all matched loops in the verification vectors are replaced with reasonable delays to avoid the usage of matched loops altogether.", +) +@click.option( + "--compress", + "-c", + is_flag=True, + default=False, + show_default=True, + help="Compress all vectors by merging subsequent identical vectors into a single vector with increased repeat value.", +) +@click.option("--pulp/--riscv", default=False, help="If true, the RISC-V TAP is used.") +@click.option( + "--wait-cycles", + type=click.IntRange(0), + default=6, + show_default=True, + help="The number of cycles to wait for the read operation to complete. Only relevant for PULP tap and not loop", +) +@pass_VectorWriter +def write_mem( + vector_writer: HP93000VectorWriter, + address_value_mappings, + verify, + loop, + compress, + pulp, + wait_cycles, +): + """ + Perform write transactions to the system bus. + + Each value of ADDRESS_VALUE_MAPPING should be of the kind 'address=value[#Comment]' where + address and value are 32-bit value in hex notation and comment is an optional comment to attach to the vectors. + E.g.:: + + write_mem "0x1c008080=0xdeafbeef#Write to start address" 0x1c008084=0x12345678 + + If the optional verify flag is provided, the data written will be read back for verification. + """ + # Parse all address value mappings and store the result in a list of tuples + data = [] + pattern = re.compile( + r"(?P
0x[0-9a-f]{8})=(?P0x[0-9a-fA-F]{0,8})(?:#(?P.*))?" + ) + + # Use stdin if the user did not provide any arguments + if not address_value_mappings: + address_value_mappings = click.get_text_stream("stdin") + for mapping in address_value_mappings: + match = pattern.match(mapping) + if not match: + raise click.BadArgumentUsage( + "Illegal argument: {}. Must be of the form 0x<32-bit address>=0x#comment".format( + mapping + ) + ) + else: + data.append( + ( + BitArray(match.group("address")), + BitArray(match.group("value")), + match.group("comment"), + ) + ) + + with vector_writer as writer: + if pulp: + vectors = pulp_tap.init_pulp_tap() + else: + vectors = riscv_debug_tap.init_dmi() + vectors += riscv_debug_tap.set_sbcs(True) + for address, value, comment in data: + if pulp: + vectors += pulp_tap.write32( + start_addr=address, data=[value], comment=comment if comment else "" + ) + else: + vectors += riscv_debug_tap.writeMem( + addr=address, data=value, comment=comment if comment else "" + ) + writer.write_vectors(vectors, compress=compress) + if verify: + for address, value, comment in data: + if loop: + if pulp: + vectors = pulp_tap.read32( + start_addr=address, expected_data=[value], comment=comment + ) + else: + vectors = riscv_debug_tap.readMem( + addr=address, expected_data=value, comment=comment + ) + else: + if pulp: + vectors = pulp_tap.read32_no_loop( + start_addr=address, + expected_data=[value], + wait_cycles=wait_cycles, + comment=comment if comment else "", + ) + else: + vectors = riscv_debug_tap.readMem_no_loop( + addr=address, + expected_data=value, + wait_cycles=wait_cycles, + comment=comment, + ) + writer.write_vectors(vectors, compress=compress) + + +@kairos.command() +@click.argument("address_value_mappings", nargs=-1) +@click.option( + "--loop/--no-loop", + default=False, + help="If true, all matched loops in the verification vectors are replaced with reasonable delays to avoid the usage of matched loops altogether.", +) +@click.option( + "--compress", + "-c", + is_flag=True, + default=False, + show_default=True, + help="Compress all vectors by merging subsequent identical vectors into a single vector with increased repeat value.", +) +@click.option( + "--use-pulp-tap", + is_flag=True, + default=False, + show_default=True, + help="Use the PULP TAP for readout instead of the RISC-V Debug module.", +) +@click.option( + "--wait-cycles", + type=click.IntRange(0), + default=6, + show_default=True, + help="The number of cycles to wait for the read operation to complete. Only relevant when pulp-tap is used", +) +@pass_VectorWriter +def verify_mem( + vector_writer: HP93000VectorWriter, + address_value_mappings, + loop, + compress: bool, + use_pulp_tap: bool, + wait_cycles: int, +): + """ + Perform read transactions on the system bus and compare the values with expected ones + + Each value of ADDRESS_VALUE_MAPPING should be of the kind 'address=value[#Comment]' where + address and value are 32-bit value in hex notation and comment is an optional comment to attach to the vectors. + E.g.:: + + verify_mem "0x1c008080=0xdeadbeef#Expecting to read 0xdeadbeef from start address" 0x1c008084=0x12345678 + + """ + # Parse all address value mappings and store the result in a list of tuples + data = [] + pattern = re.compile( + r"(?P
0x[0-9a-f]{8})=(?P0x[0-9a-fA-F]{0,8})(?:#(?P.*))?" + ) + for mapping in address_value_mappings: + match = pattern.match(mapping) + if not match: + raise click.BadArgumentUsage( + "Illegal argument: {}. Must be of the form 0x<32-bit address>=0x#comment".format( + mapping + ) + ) + else: + data.append( + ( + BitArray(match.group("address")), + BitArray(match.group("value")), + match.group("comment"), + ) + ) + + with vector_writer as writer: + vector_builder.init() + if use_pulp_tap: + vectors = pulp_tap.init_pulp_tap() + else: + vectors = riscv_debug_tap.init_dmi() + vectors += riscv_debug_tap.set_sbcs(True) + for address, value, comment in data: + if loop: + if use_pulp_tap: + vectors += pulp_tap.read32( + start_addr=address, expected_data=[value], comment=comment + ) + else: + vectors += riscv_debug_tap.readMem( + addr=address, expected_data=value, comment=comment + ) + else: + if use_pulp_tap: + vectors += pulp_tap.read32_no_loop( + start_addr=address, + expected_data=[value], + wait_cycles=wait_cycles, + comment=comment if comment else "", + ) + else: + vectors += riscv_debug_tap.readMem_no_loop( + addr=address, + expected_data=value, + wait_cycles=wait_cycles, + comment=comment, + ) + writer.write_vectors(vectors, compress=compress) + + +@kairos.command() +@click.option( + "--wait-cycles", + "-w", + type=click.IntRange(min=1), + default=6, + show_default=True, + help="The number of cycles to wait before verifying that core was actually resumed.", +) +@pass_VectorWriter +def resume_core(vector_writer: HP93000VectorWriter, wait_cycles): + """ + Generate vectors to resume the core. + + The vectors will instruct the RISC-V debug module via JTAG to resume the core and after a configurable number of + JTAG clock cycles will verify that the core is in the 'running' state.""" + + with vector_writer as writer: + vectors = riscv_debug_tap.init_dmi() + + vectors += riscv_debug_tap.resume_harts(FC_CORE_ID,"Resuming core", retries=16) + + #vectors += riscv_debug_tap.resume_harts_no_loop( + # FC_CORE_ID, "Resuming core", wait_cycles=wait_cycles + #) + + writer.write_vectors(vectors) + + +@kairos.command() +@click.option( + "--reset-cycles", + "-r", + type=click.IntRange(min=1), + default=10, + show_default=True, + help="The number of cycles to assert the chip reset line.", +) +@pass_VectorWriter +def reset_chip(vector_writer: HP93000VectorWriter, reset_cycles): + """ + Generate vectors to reset the core and the jtag interface + + """ + with vector_writer as writer: + vectors = [] + vector_builder.chip_reset = 0 + vectors += [vector_builder.vector(reset_cycles, comment="Assert chip reset")] + vector_builder.chip_reset = 1 + vectors += jtag_driver.jtag_reset() + vectors += jtag_driver.jtag_idle_vectors(10) + vectors += riscv_debug_tap.init_dmi() + vectors += riscv_debug_tap.set_dmactive(True) + vectors += jtag_driver.jtag_idle_vectors(100000) + writer.write_vectors(vectors) + + +@kairos.command() +@click.option( + "--pc", + type=str, + help="Read programm counter and compare it with the expected value provided", +) +@click.option( + "--resume", + show_default=True, + default=False, + help="Resume the core after reading the program counter.", +) +@click.option( + "--assert-reset", + is_flag=True, + show_default=True, + default=False, + help="Assert the chip reset line for the whole duration of the generated vectors.", +) +@click.option( + "--wait-cycles", + "-w", + type=click.IntRange(min=1), + default=6, + show_default=True, + help="The number of cycles to wait before verifying that core was actually halted.", +) +@pass_VectorWriter +def halt_core_verify_pc( + vector_writer: HP93000VectorWriter, pc, resume, assert_reset, wait_cycles +): + """Halt the core, optionally reading the program counter and resuming the core. + + This command is mainly useful to verify or debug the execution state of a program. The generated vectors will halt + the core, optionally read the programm counter and optionally resume the core. + + E.g.:: + dumpling kairos -o halt_core halt_core_verify_pc --pc 0x1c008080 --resume + + Will halt the core, comparing the programm counter to the value 0x1c008080 and resuming the core afterwards. + + The --assert-reset flag allows to keep the reset line asserted during the exeuction of core halt procedure. This + allows to halt the core before it statrts to execute random data right after reset. + """ + + with vector_writer as writer: + if assert_reset: + vector_builder.chip_reset = 0 + vectors = riscv_debug_tap.init_dmi() + vectors += riscv_debug_tap.halt_hart_no_loop( + FC_CORE_ID, wait_cycles=wait_cycles + ) + if pc: + expected_pc = BitArray(pc) + expected_pc = (32 - len(expected_pc)) + expected_pc # Extend to 32-bit + vectors += riscv_debug_tap.read_reg_abstract_cmd_no_loop( + RISCVReg.CSR_DPC, + BitArray(expected_pc, length=32).bin, + wait_cycles=wait_cycles, + comment="Reading DPC", + ) + if resume: + vectors += riscv_debug_tap.resume_harts_no_loop( + FC_CORE_ID, comment="Resuming the core", wait_cycles=wait_cycles + ) + writer.write_vectors(vectors) + + +@kairos.command() +@click.option( + "--return-code", + "-r", + default=0, + type=click.IntRange(min=0, max=255), + show_default=True, + help="The expected return code.", +) +@click.option( + "--wait-cycles", + "-w", + type=click.IntRange(min=-10), + default=6, + show_default=True, + help="The number of cycles to wait for the eoc_register read operation to complete.", +) +@click.option( + "--compress", + '-c', + is_flag=True, + default=False, + show_default=True, + help="Compress all vectors by merging subsequent identical vectors into a single vector with increased repeat value." +) +@pass_VectorWriter +def check_eoc(vector_writer, return_code, wait_cycles, compress): + """Generate vectors to check for the end of computation. + + Programs compiled with the pulp-sdk or pulp-runtime write their exit code to a special end-of-computation register + in APB SOC Control when they leave main. The expected return code (by default 0) can be modified to assume any value + between 0 and 255.""" + + # Wait for end of computation by polling EOC register address + with vector_writer as writer: + if return_code != None: + if wait_cycles <= 0: + print("We are polling!") + vectors = riscv_debug_tap.wait_for_end_of_computation(return_code, idle_vector_count=500, max_retries=3000) + else: + vectors = [jtag_driver.jtag_idle_vector(repeat=wait_cycles, comment="Waiting for computation to finish before checking EOC register.")] + vectors += riscv_debug_tap.check_end_of_computation(return_code, wait_cycles=5000) + vector_writer.write_vectors(vectors, compress=compress) + + #with vector_writer as writer: + # vectors = riscv_debug_tap.init_dmi() + # vectors += riscv_debug_tap.check_end_of_computation( + # return_code, wait_cycles=wait_cycles + # ) + # writer.write_vectors(vectors) + + +@kairos.command() +@pass_VectorWriter +def verify_idcode(vector_writer): + """Generate vectors to verify IDCODE of the RISC-V debug unit. + + Puts all taps except the debug unit into bypass mode and verifies the value of the debug units IDCODE register. + In Kairos, the value should match "0x2f33ddb3". After the idcode read-out, the debug unit TAP remains selected. + """ + with vector_writer as writer: + vectors = riscv_debug_tap.verify_idcode() + writer.write_vectors(vectors) + +@kairos.command() +@click.argument("FREQ", type=click.IntRange(min=0, max=1000000000000)) +@click.option("--fll", default='SOC_FLL', type=click.Choice(['CLU_FLL','PER_FLL', 'SOC_FLL'])) +@click.option("--mult", default = '10', type=click.IntRange(min=1, max=65535)) +@click.option("--clk-div", default='4', type=click.Choice(['1','2','4','8','16','32','64','128','256']), help="Change the clock division factor of DCO clock to FLL output clock.") +@click.option("--lock", '-l', is_flag = True, default=True, show_default=True, help="Gate the output clock with the FLL lock signal") +@click.option("--tolerance", default=80, show_default=True, type=click.IntRange(min=0, max=2047), help="The margin around the target multiplication factor for clock to be considered stable.") +@click.option("--stable-cycles", default=6, show_default=True, type=click.IntRange(min=0, max=63), help="The number of stable cycles unil LOCK is asserted.") +@click.option("--unstable-cycles", default=16, show_default=True, type=click.IntRange(min=0, max=63), help="The number of unstable cycles unil LOCK is de-asserted.") +@click.option("--enable-dithering", is_flag=True, default=False, show_default=True, help="Enable dithering for higher frequency resolution.") +@click.option("--loop-gain-exponent", default=-8, type=click.IntRange(min=-15,max=0), show_default=True, help="The gain exponent of the feedback loop. Gain = 2^") +@click.option('--wait-cycles','-w', type=click.IntRange(min=1), default=200, show_default=True, help="The number of jtag cycles to wait between writing the two FLL config registers.") +@click.option("--pulp/--riscv", default=False, help="If true, the RISC-V TAP is used.") +@pass_VectorWriter +def change_freq(vector_writer: HP93000VectorWriter, freq, fll, mult, clk_div, lock, tolerance, stable_cycles, unstable_cycles, loop_gain_exponent, enable_dithering, wait_cycles, pulp): + """ Generate vectors to change the multiplication factor (MULT) and various other settings of the internal FLLs . + + The FLL argument determines which of the two independent FLLs in Kairos is configured. + + The output frequency of the FLL is freq =*/. + + Since we need to write to two registers, we have to wait long enough for the FLL to become stable again before we try to modify the second registers. + + """ + + # TODO: optionally write to a specific address in the memory space and read + #the frequency value from software. For now, uncomment if needed. + #magic_address = BitArray('0x1c040000') + + if fll == "SOC_FLL": + config1_address = BitArray('0x1a100004') + config2_address = BitArray('0x1a100008') + config3_address = BitArray('0x1a10000c') + elif fll == "PER_FLL": + config1_address = BitArray('0x1a100014') + config2_address = BitArray('0x1a100018') + else: + config1_address = BitArray('0x1a100024') + config2_address = BitArray('0x1a100028') + clk_div_value = int(math.log2(int(clk_div)))+1 + config1_value = bitstring.pack('0b1, bool, uint:4, uint:10=344, uint:16', lock, clk_div_value, mult) + + freq_value = bitstring.pack('uint:32', freq) + + config2_value = bitstring.pack('bool, 0b000, uint:12, uint:6, uint:6, uint:4', + enable_dithering, + tolerance, + stable_cycles, unstable_cycles, -loop_gain_exponent) + + config3_value = bitstring.pack('uint:6=0, uint:10=322, uint:16=0') + + with vector_writer as writer: + if pulp: + # Init pulp tap + vectors = pulp_tap.init_pulp_tap() + # Set FLL registers + vectors += pulp_tap.write32(start_addr=config1_address, data=[config1_value], comment="[PULP_TAP] Configure {}".format(fll)) + vectors += [jtag_driver.jtag_idle_vector(repeat=wait_cycles)] + vectors += pulp_tap.write32(start_addr=config2_address, data=[config2_value], comment="[PULP_TAP] Configure {}".format(fll)) + #vectors += pulp_tap.write32(start_addr=magic_address, data=[freq_value], comment="[PULP_TAP] Configure {}".format(fll)) + + vectors += [jtag_driver.jtag_idle_vector(repeat=wait_cycles)] + else: + # Init riscv debug module + vectors = riscv_debug_tap.init_dmi() + vectors += riscv_debug_tap.set_sbcs(True) + # Set FLL registers + vectors += riscv_debug_tap.writeMem(addr=config2_address, data=config2_value, comment="[RISCV_DBG] Configure {}".format(fll)) + vectors += riscv_debug_tap.writeMem(addr=config3_address, data=config3_value, comment="[RISCV_DBG] Configure {}".format(fll)) + vectors += riscv_debug_tap.readMem(addr=config1_address, expected_data=config3_value, comment='') + vectors += [jtag_driver.jtag_idle_vector(repeat=50)] + vectors += riscv_debug_tap.writeMem(addr=config1_address, data=config1_value, comment="[RISCV_DBG] Configure {}".format(fll)) + #vectors += riscv_debug_tap.writeMem(addr=magic_address, data=freq_value, comment="[RISCV_DBG] Configure {}".format(fll)) + + vectors += [jtag_driver.jtag_idle_vector(repeat=wait_cycles)] + + writer.write_vectors(vectors) From 0a0c6e25cdd65a2edae008002e9dcd25738e49b5 Mon Sep 17 00:00:00 2001 From: aottaviano Date: Sat, 22 Jun 2024 17:05:48 +0200 Subject: [PATCH 2/2] src: Fix Siracusa-related info in comments --- src/dumpling/Chips/Siracusa.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dumpling/Chips/Siracusa.py b/src/dumpling/Chips/Siracusa.py index 97b86c9..53095c0 100644 --- a/src/dumpling/Chips/Siracusa.py +++ b/src/dumpling/Chips/Siracusa.py @@ -150,7 +150,7 @@ vector_builder = VectorBuilder(pins) jtag_driver = JTAGDriver(vector_builder) -# Instantiate the two JTAG taps in vega +# Instantiate the two JTAG taps in siracusa riscv_debug_tap = RISCVDebugTap(jtag_driver) pulp_tap = PULPJtagTap(jtag_driver) # Add the taps to the jtag chain in the right order @@ -162,7 +162,7 @@ pass_VectorWriter = click.make_pass_decorator(HP93000VectorWriter) -# Entry point for all vega related commands +# Entry point for all siracusa related commands @click.group() @click.option( "--port-name", "-p", type=str, default="jtag_and_reset_port", show_default=True @@ -183,7 +183,7 @@ ) @click.pass_context def siracusa(ctx, port_name, wtb_name, device_cycle_name, output): - """Generate stimuli for the GF22 vega chip.""" + """Generate stimuli for the TSMC16 Siracusa chip.""" # Instantiate the vector writer and attach it to the command context so subcommands can access it. vector_builder.init() ctx.obj = HP93000VectorWriter( @@ -627,7 +627,7 @@ def halt_core_verify_pc( the core, optionally read the programm counter and optionally resume the core. E.g.:: - dumpling vega -o halt_core.avc halt_core_verify_pc --pc 0c1c008080 --resume + dumpling siracusa -o halt_core.avc halt_core_verify_pc --pc 0c1c008080 --resume Will halt the core, comparing the programm counter to the value 0x1c008080 and resuming the core afterwards.