<div dir="auto">Thank you, Mark. </div><div dir="auto"><br></div><div dir="auto">It’s posted to the ORI website as a blog entry, but there are no plans to publish it elsewhere. We do not mind if it’s forwarded to Hack-a-Day. </div><div dir="auto"><br></div><div dir="auto">I’ll be on travel through the 10th, so would you please take the lead on a submission?</div><div dir="auto"><br></div><div dir="auto">-Michelle</div><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Dec 4, 2022 at 22:43 Mark Whittington <<a href="mailto:markwhi@gmail.com">markwhi@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)"><div dir="ltr"><div dir="auto">Michelle and Paul:</div><div dir="auto"><br></div><div dir="auto">This was a fascinating read! I have seen a lot of coverage of AI-generated code (mostly GitHub's Copilot) but this is the first test case that I've seen involving an HDL. Do you plan to publish this work somewhere other than this list?  Would you mind if I forward it to the editors at Hack-a-Day, or would you consider doing so yourselves?</div><div dir="auto"><br></div><div dir="auto">Thank you both for the write-up and to anyone else involved!</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Dec 3, 2022, 1:31 PM Michelle Thompson via Ground-Station <ground-station@lists.openresearch.institute> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)">Greetings all,<br>
<br>
You know that ORI has been active in a variety of regulatory work for<br>
several years now. One of those areas has been in AI/ML and the effect<br>
on communications. We served on the US FCC TAC in 2022, presented on<br>
the subject, and are working towards an AI/ML Handbook for Amateur<br>
Radio.<br>
<br>
You may have seen news about OpenAI GPT, or ChatGPT.<br>
<br>
There's a lot of people testing this chatbot out for reverse<br>
engineering and in writing software. There's been some successes in<br>
cases where the model would have had access to code or documentation<br>
about protocols, observations, or technical behavior in order to<br>
train, and requests match up well with the models.<br>
<br>
For example, a friend asked the chatbot to create a Python script to<br>
access the webcam on their computer, and they shared a still image<br>
from the resulting feed. Another example from another friend resulted<br>
in better reverse engineering results than they had gotten with either<br>
IDA or Ghidra over many weeks.<br>
<br>
So, how does ChatGPT handle VHDL?<br>
<br>
We have something specific to compare against, since we just completed<br>
a COBS decoder in VHDL for our open source HEO/GEO transponder work<br>
for Haifuraiya.<br>
<br>
Let's start off simple. Here's the first dialogue with the chatbot,<br>
and the results.<br>
<br>
-=-=-=-=-=-=-=-=-=-=-=-=-=-<br>
<br>
Abraxas3d: Design a COBS decoder in VHDL<br>
<br>
Sure, here's an example of a COBS decoder in VHDL:<br>
<br>
<br>
<br>
library IEEE;<br>
use IEEE.STD_LOGIC_1164.ALL;<br>
<br>
entity COBS_decoder is<br>
  Port (<br>
    input_data : in std_logic_vector;<br>
    decoded_data : out std_logic_vector<br>
  );<br>
end COBS_decoder;<br>
<br>
architecture Behavioral of COBS_decoder is<br>
  -- Declare a variable to keep track of the current index<br>
  -- in the input and output data streams<br>
  variable current_index : integer := 1;<br>
<br>
  -- Declare a variable to store the length of the<br>
  -- run of zeros in the input data<br>
  variable zero_run_length : integer := 0;<br>
begin<br>
  -- Iterate over the input data<br>
  for i in input_data'range loop<br>
    -- If the current input value is a zero, increment<br>
    -- the zero run length variable<br>
    if input_data(i) = '0' then<br>
      zero_run_length := zero_run_length + 1;<br>
    -- Otherwise, the current input value is not a zero,<br>
    -- so we've reached the end of the zero run<br>
    else<br>
      -- Set the decoded value at the current index to<br>
      -- the length of the zero run<br>
      decoded_data(current_index) := conv_std_logic_vector(zero_run_length, 8);<br>
<br>
      -- Increment the current index and reset the zero<br>
      -- run length for the next iteration<br>
      current_index := current_index + 1;<br>
      zero_run_length := 0;<br>
    end if;<br>
  end loop;<br>
end Behavioral;<br>
<br>
This code decodes the input data using the COBS (Consistent Overhead<br>
Byte Stuffing) algorithm, which involves replacing runs of zeros in<br>
the input data with a single byte that indicates the length of the<br>
zero run. For example, the input '101001000' would be decoded as<br>
'103101'.<br>
<br>
This decoder iterates over the input data and maintains a variable<br>
zero_run_length that is incremented for each zero in the input data.<br>
When a non-zero value is encountered, the length of the zero run is<br>
written to the output data and the zero_run_length variable is reset.<br>
<br>
I hope this helps! Let me know if you have any other questions."<br>
<br>
-=-=-=-=-=-=-=-=-=-=-=-=-=-<br>
<br>
It knew what COBS meant. It produced code, with comments, and a brief<br>
"design document", with examples.<br>
<br>
Our open source HEO transponder project uses AXI-based blocks in the<br>
FPGA. So, let's add AXI to the request.<br>
<br>
-=-=-=-=-=-=-=-=-=-=-=-=-=-<br>
<br>
Abraxas3d: Design a COBS decoder with AXI interface in VHDL<br>
<br>
Sure, here's an example of a COBS decoder with an AXI interface in VHDL:<br>
<br>
library IEEE;<br>
use IEEE.STD_LOGIC_1164.ALL;<br>
use IEEE.NUMERIC_STD.ALL;<br>
<br>
-- AXI interface definitions<br>
library unisim;<br>
use unisim.vcomponents.all;<br>
<br>
entity COBS_decoder is<br>
  Port (<br>
    AXI_IN  : in  AXI4Stream;<br>
    AXI_OUT : out AXI4Stream<br>
  );<br>
end COBS_decoder;<br>
<br>
architecture Behavioral of COBS_decoder is<br>
  -- Declare a variable to keep track of the current index<br>
  -- in the input and output data streams<br>
  variable current_index : integer := 1;<br>
<br>
  -- Declare a variable to store the length of the<br>
  -- run of zeros in the input data<br>
  variable zero_run_length : integer := 0;<br>
begin<br>
  -- Iterate over the input data<br>
  for i in AXI_IN.data'range loop<br>
    -- If the current input value is a zero, increment<br>
    -- the zero run length variable<br>
    if AXI_IN.data(i) = '0' then<br>
      zero_run_length := zero_run_length + 1;<br>
    -- Otherwise, the current input value is not a zero,<br>
    -- so we've reached the end of the zero run<br>
    else<br>
      -- Set the decoded value at the current index to<br>
      -- the length of the zero run<br>
      AXI_OUT.data(current_index) := conv_std_logic_vector(zero_run_length, 8);<br>
<br>
      -- Increment the current index and reset the zero<br>
      -- run length for the next iteration<br>
      current_index := current_index + 1;<br>
      zero_run_length := 0;<br>
    end if;<br>
  end loop;<br>
<br>
  -- Set the valid and last flags in the output AXI stream<br>
  AXI_OUT.valid <= '1';<br>
  AXI_OUT.last  <= '1';<br>
end Behavioral;<br>
<br>
This code is similar to the previous example, but it uses an AXI<br>
(Advanced eXtensible Interface) interface for the input and output<br>
data. The AXI interface is a standard interface used in many FPGA<br>
designs, and it provides a way to stream data into and out of the<br>
decoder.<br>
<br>
In this code, the input data is read from the AXI_IN.data port, and<br>
the decoded output is written to the AXI_OUT.data port. The valid and<br>
last flags are also set in the output AXI stream to indicate that the<br>
data is valid and that it is the last data in the stream.<br>
<br>
I hope this helps! Let me know if you have any other questions.<br>
<br>
-=-=-=-=-=-=-=-=-=-=-=-=-=-<br>
<br>
It knows about the previous request and updated the design.<br>
<br>
Here's a review of the COBS implementation from Paul Williamson KB5MU.<br>
<br>
"I don’t know what this is, but it isn’t a COBS decoder with AXI interfaces.<br>
<br>
It does seem at first glance to be some sort of thing with AXI<br>
interfaces, but it does not implement an AXI interface at all. It just<br>
relies on a (possibly imaginary) library type called AXI4Stream that<br>
somehow magically does AXI interfaces, in a way that’s both<br>
implausibly smart and unexplicably dumb. I think the classic phrase<br>
“not even wrong” applies here.<br>
<br>
The AXI4Stream object apparently has a member .data that is an array<br>
of bytes, which might make sense if the entire AXI transfer is being<br>
treated as a single entity here. The code iterates through the input<br>
.data using the ’range attribute, as if the AXI4Stream object has a<br>
defined fixed transfer length.<br>
<br>
Which it can’t have, if it’s a general purpose AXI stream implementation.<br>
<br>
So, if this was ever anything real, it must have been a special<br>
purpose AXI implementation with a fixed transfer length. Assuming that<br>
the AXI4Stream .data actually works that way, the entity does<br>
do some sort of transformation on the input data to create the output data.<br>
<br>
We asked for that to be a COBS decoder, but the function that it<br>
actually implements bears only the slightest resemblance to a COBS<br>
decoder. What it actually does is output a stream of words that are<br>
the lengths of the runs of zeroes in the input data. Nonzero data does<br>
not get passed through at all.<br>
<br>
Instead, a run of nonzero bytes gets translated into a run of zeroes,<br>
as if two adjacent nonzero bytes meant nothing but a zero-length run<br>
of zeroes.<br>
<br>
Here’s an example of what this code seems to do:<br>
  Input  .data:  1 2 3 4 0 0 0 0 1 2 3 4<br>
  Output .data:  0 0 0 0         4 0 0 0<br>
<br>
That’s certainly not a COBS decoder, or even anything useful at all.<br>
<br>
Note that the output is variable length, but never longer than the input.<br>
We had to assume that the AXI4Stream object had a fixed .data size to<br>
get this far, but now it has to have a variable data size for the<br>
output.<br>
<br>
Supposing we had successfully suspended disbelief up to here, we now<br>
examine the final two lines of code in the Behavioral architecture. It<br>
sets the .valid and .last members of the AXI_OUT port to ‘1’.<br>
<br>
That makes absolutely no sense if it’s supposed to encapsulate an<br>
entire AXI stream transfer. Those signals only make sense if we’re<br>
treating one word at a time, as you’d expect to see in a normal,<br>
general-purpose AXI stream object.<br>
<br>
The extremely verbose commenting style in this code suggests that the<br>
original source material was from an introductory tutorial. Maybe the<br>
AI has been tuned to favor heavily commented code, and ends up picking<br>
up partially completed junk from the middle of tutorials?<br>
Anyhow, this is not an example of automated programming in response to<br>
a high-level query. This is gibberish that succeeds only in having a<br>
superficial resemblance to the code requested."<br>
<br>
So, does this work?<br>
<br>
Let's try it out in the lab!<br>
<br>
The first thing we notice is that there is an obvious syntax error<br>
with a missing semicolon. Aside from that, there is no AXI4Stream port<br>
type. It's not recognized. Vivado appears to be disappointed in this<br>
file, and wants little to do with this code. This is where we should<br>
stop, but I spent some time looking to see if the ports were at least<br>
close to being declared correctly.<br>
<br>
The model appears to have taken some custom or maybe enumerated type<br>
from somewhere, and come up with a custom AXI4Stream type. This is not<br>
recognized by the unisim library right off the bat, and that's the<br>
sort of thing that automated code writing needs to get right.<br>
<br>
Let's look at the code written by humans from ORI.<br>
<br>
-=-=-=-=-=-=-=-=-=-=-=-=-=-<br>
<br>
----------------------------------------------------------------------------------<br>
-- Company: Open Research Institute, Inc.<br>
-- Engineer: Skunkwrx, Abraxas3d<br>
-- <br>
-- Design Name: COBS protocol decoder<br>
-- Module Name: decoder - Behavioral<br>
-- Project Name: Phase 4 "Haifuraiya"<br>
-- Target Devices: 7000 Zynq<br>
-- Tool Versions: 2021.1<br>
-- Description: COBS protocol decoder.<br>
--              <a href="https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing" rel="noreferrer noreferrer" target="_blank">https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing</a><br>
-- <br>
-- Dependencies:<br>
--<br>
-- Additional Comments: This work is Open Source and licensed using<br>
CERN OHL v2.0<br>
-- <br>
----------------------------------------------------------------------------------<br>
<br>
<br>
library IEEE;<br>
use IEEE.STD_LOGIC_1164.ALL;<br>
<br>
use IEEE.NUMERIC_STD.ALL;<br>
<br>
--Entity Declaration<br>
entity decoder is<br>
    Port ( rst      : in STD_LOGIC;<br>
           clk      : in STD_LOGIC;<br>
           s_tdata  : in STD_LOGIC_VECTOR (7 downto 0);<br>
           s_tlast  : in STD_LOGIC;<br>
           s_tvalid : in STD_LOGIC;<br>
           s_tready : out STD_LOGIC;<br>
           m_tdata  : out STD_LOGIC_VECTOR (7 downto 0);<br>
           m_tlast  : out STD_LOGIC;<br>
           m_tvalid : out STD_LOGIC;<br>
           m_tready : in STD_LOGIC);<br>
end decoder;<br>
<br>
--Architecture<br>
architecture Behavioral of decoder is<br>
<br>
-- internal copy of s_tdata<br>
    signal input_data          : STD_LOGIC_VECTOR (7 downto 0);<br>
<br>
    -- s_tdata delayed by one clk where s_tvalid is high<br>
    signal input_data_d        : STD_LOGIC_VECTOR (7 downto 0);<br>
<br>
    -- internal version of s_tlast<br>
    -- not used for anything<br>
    -- We create our own m_tlast from the COBS framing instead<br>
    signal s_tlast_i           : STD_LOGIC;<br>
<br>
    -- internal version of input handshaking signal s_tvalid<br>
    signal s_tvalid_i          : STD_LOGIC;<br>
<br>
    -- s_tvalid delayed by one clk<br>
    -- thus, a version of s_tvalid aligned with input_data_d<br>
    signal s_tvalid_i_d        : STD_LOGIC;<br>
<br>
    -- s_tvalid delayed by two clks<br>
    -- thus, a version of s_tvalid aligned with output_data<br>
    signal s_tvalid_i_d_d      : STD_LOGIC;<br>
<br>
    -- countdown of bytes in this sequence<br>
    -- loads from input_data_d when it represents the frame count<br>
    --   as determined by signal counter_load<br>
    -- contains the count while m_tdata contains the implied 0 at<br>
    --   the end of a sequence, or the next count that replaced it<br>
    -- counts down thereafter, to contain 1 when the last non-zero<br>
    --   byte of the sequence is on m_tdata<br>
    -- allowed to count down to 0, but not beyond<br>
    signal count               : STD_LOGIC_VECTOR (7 downto 0);<br>
<br>
-- enable to load count from input_data_d on this clk edge<br>
-- two cases detected:<br>
--    * first valid non-zero byte after a frame separator<br>
--    * first valid byte after count is exhausted<br>
-- allowed to be high for multiple cycles<br>
    signal counter_load        : STD_LOGIC;<br>
<br>
    -- counter_load delayed by one clk where s_tvalid is high<br>
    -- used to identify the first valid data byte of any sequence,<br>
    --   for purposes of computing m_tvalid (via pre_tvalid)<br>
    signal counter_load_d      : STD_LOGIC;<br>
<br>
    -- detection of a valid frame separator (zero) byte in input_data_d<br>
    signal frame_sep           : STD_LOGIC;<br>
<br>
    -- frame_sep delayed by one clk where s_tvalid is high<br>
    -- used to compute counter_load<br>
    -- used to compute rising edge of pre_tvalid<br>
    signal frame_sep_d         : STD_LOGIC;<br>
<br>
    -- frame_sep_d delayed by an additional clk (not depending on s_tvalid)<br>
    -- used to find the first non-zero byte of the new frame<br>
    signal frame_sep_d_d       : STD_LOGIC;<br>
<br>
    -- move the frame_sep signal that occurred during m_tready low<br>
    -- out to the first cycle when m_tready is high again<br>
    signal use_saved_frame_sep : STD_LOGIC;<br>
<br>
    -- flag to remember that the frame count for this sequence was 255,<br>
    --   to handle the special case that such a sequence does not have<br>
    --   an implied zero byte at the end.<br>
    -- set when loading count with 255<br>
    -- cleared when the counter is reloaded with anything else<br>
    signal case_255            : STD_LOGIC;<br>
<br>
    -- internal version of m_tdata output<br>
    signal output_data         : STD_LOGIC_VECTOR (7 downto 0);<br>
<br>
    -- internal version of m_tlast output<br>
    -- high when the last byte of a frame is valid on m_tdata<br>
    signal m_tlast_i           : STD_LOGIC;<br>
<br>
    -- delayed versions of m_tlast<br>
    signal m_tlast_i_d         : STD_LOGIC;<br>
    signal m_tlast_i_d_d       : STD_LOGIC;<br>
<br>
    -- intermediate result for m_tvalid.<br>
    -- high across all data bytes of each sequence on m_tdata<br>
    -- does not go low for bytes on m_tdata corresponding to<br>
    --   bytes invalidated by s_tvalid.<br>
    signal pre_tvalid          : STD_LOGIC;<br>
<br>
    -- internal version of m_tvalid output.<br>
    -- pre_tvalid with periods of low s_tvalid_d_d punched out<br>
    signal m_tvalid_i          : STD_LOGIC;<br>
<br>
    -- internal version of m_tready input<br>
    -- also the internal version of s_tready output<br>
    -- passes through m_tready to s_tready with no clk delays<br>
    signal m_tready_i          : STD_LOGIC;<br>
<br>
    -- constant byte value 0xFF, for comparison purposes<br>
    signal all_ones            : STD_LOGIC_VECTOR(input_data'range) :=<br>
(others => '1');<br>
<br>
    -- constant byte value 0x00, for comparison purposes<br>
    signal all_zeros           : STD_LOGIC_VECTOR(input_data'range) :=<br>
(others => '0');<br>
<br>
begin<br>
<br>
    -- asynchronous assignments<br>
<br>
    frame_sep <= '1' when input_data_d = all_zeros and s_tvalid_i_d = '1'<br>
                else '0';<br>
<br>
    m_tlast_i <= '1' when ((frame_sep = '1' and m_tvalid_i = '1' and<br>
m_tready = '1'))<br>
                else '0';<br>
<br>
    counter_load <= '1' when (input_data_d /= all_zeros and<br>
frame_sep_d = '1' and s_tvalid_i_d = '1')   -- start of frame<br>
                          or (to_integer(unsigned(count)) = 1 and<br>
s_tvalid_i_d = '1')   -- start of next sequence in frame<br>
                else '0';<br>
<br>
    m_tvalid_i <= '1' when ((pre_tvalid = '1' and s_tvalid_i_d_d = '1'<br>
   -- usual case, if input_data was valid<br>
                        and not (to_integer(unsigned(count)) = 1 and<br>
s_tvalid_i_d = '0')) -- defer last byte; might be m_tlast<br>
                      or (pre_tvalid = '1' and to_integer(unsigned(count)) = 1<br>
                        and s_tvalid_i_d = '1' and s_tvalid_i_d_d =<br>
'0')) -- pick up that deferred last byte<br>
                else '0';<br>
<br>
<br>
    s_tready <= m_tready_i;<br>
    m_tdata <= output_data;<br>
    input_data <= s_tdata;<br>
    s_tvalid_i <= s_tvalid;<br>
    m_tready_i <= m_tready;<br>
    m_tvalid <= m_tvalid_i;<br>
    m_tlast <= m_tlast_i;<br>
<br>
-- processes<br>
<br>
<br>
<br>
    set_case_255 : process (rst, clk)<br>
    begin<br>
        if rst = '1' then<br>
            case_255 <= '0';<br>
        elsif rising_edge(clk) and m_tready_i = '1' then<br>
            if counter_load = '1' and input_data_d = all_ones then<br>
                case_255 <= '1';<br>
            elsif counter_load = '1' and input_data_d /= all_ones then<br>
                case_255 <= '0';<br>
            end if;<br>
        end if;<br>
    end process set_case_255;<br>
<br>
<br>
<br>
    delay_s_tvalid : process (rst, clk)<br>
    begin<br>
        if rst = '1' then<br>
            s_tvalid_i_d <= '0';<br>
            s_tvalid_i_d_d <= '0';<br>
        elsif rising_edge(clk) and m_tready_i = '1' then<br>
            s_tvalid_i_d <= s_tvalid_i;<br>
            s_tvalid_i_d_d <= s_tvalid_i_d;<br>
        end if;<br>
    end process delay_s_tvalid;<br>
<br>
<br>
<br>
    create_pre_tvalid : process (rst, clk)<br>
    begin<br>
        if rst = '1' then<br>
            counter_load_d <= '0';<br>
            pre_tvalid <= '0';<br>
        elsif rising_edge(clk) and m_tready_i = '1' then<br>
            if s_tvalid_i_d = '1' then<br>
                counter_load_d <= counter_load;<br>
                if (frame_sep_d_d = '1' and frame_sep_d = '0')<br>
   -- normal last byte of frame<br>
                or (counter_load_d = '1' and frame_sep_d = '0')<br>
   -- normal first byte of a sequence<br>
                then<br>
                    pre_tvalid <= '1';<br>
                end if;<br>
            end if;<br>
            if frame_sep = '1'<br>
            then<br>
                pre_tvalid <= '0';<br>
            end if;<br>
            if counter_load = '1' and case_255 = '1' then<br>
                pre_tvalid <= '0';<br>
            end if;<br>
        end if;<br>
    end process create_pre_tvalid;<br>
<br>
<br>
<br>
    delay_m_tlast_i : process (rst, clk)<br>
    begin<br>
        if rst = '1' then<br>
            m_tlast_i_d <= '0';<br>
            m_tlast_i_d_d <= '0';<br>
        elsif rising_edge(clk) and m_tready_i = '1' then<br>
            m_tlast_i_d <= m_tlast_i;<br>
            m_tlast_i_d_d <= m_tlast_i_d;<br>
        end if;<br>
    end process delay_m_tlast_i;<br>
<br>
<br>
<br>
    set_counter : process (rst,clk)<br>
    begin<br>
        if rst = '1' then<br>
            count <= (others => '0');<br>
            frame_sep_d <= '0';<br>
            frame_sep_d_d <= '0';<br>
        elsif rising_edge(clk) and m_tready_i = '1' then<br>
            frame_sep_d_d <= frame_sep_d;<br>
            if s_tvalid_i_d = '1' then<br>
                frame_sep_d <= frame_sep;<br>
                if counter_load = '1' then<br>
                    count <= input_data_d;<br>
                elsif count /= all_zeros<br>
                then<br>
                    count <= STD_LOGIC_VECTOR(unsigned(count) - 1);<br>
                end if;<br>
            end if;<br>
        end if;<br>
    end process set_counter;<br>
<br>
<br>
<br>
    create_output : process (rst, clk)<br>
    begin<br>
        if rst = '1' then<br>
            output_data <= (others => '0');<br>
        elsif rising_edge(clk) and m_tready_i = '1' then<br>
            if counter_load = '1'<br>
            then<br>
                output_data <= all_zeros;<br>
            elsif s_tvalid_i_d = '1' then<br>
                output_data <= input_data_d;<br>
            end if;<br>
        end if;<br>
    end process create_output;<br>
<br>
<br>
<br>
    selective_delay_of_input_data : process (rst,clk)<br>
    begin<br>
        if rst = '1' then<br>
            input_data_d <= all_zeros;<br>
        elsif rising_edge(clk) and m_tready_i = '1' then<br>
            if s_tvalid_i = '1' then<br>
                input_data_d <= input_data;<br>
            end if;<br>
        end if;<br>
    end process selective_delay_of_input_data;<br>
<br>
<br>
end Behavioral;<br>
<br>
-=-=-=-=-=-=-=-=-=-=-=-=-=-<br>
<br>
This codebase doesn't include just the source code, but also a<br>
testbench file, a design document, timing diagrams, a python notebook<br>
that creates test vectors, and python code that compares results<br>
produced by the testbench that uses the test vectors. None of that is<br>
produced by ChatGPT.<br>
<br>
There is code in some languages that can be written by AI at this point.<br>
<br>
This is a situation similar to algorithmic musical composition.<br>
Algorithms can come up with ideas, sketches, or traverse a search<br>
space more quickly than a human. They can help a composer, but do not<br>
replace one. Algorithms can produce some sparkling gems of ideas.<br>
These are fresh cuts and views. This is mixed in with a lot of music<br>
that is just plain wrong.<br>
<br>
If your programming job happens to be in a well-defined area that is<br>
easily automated, then you have something to worry about today. All<br>
jobs are a target for automation. Yes, all of them. As AI/ML becomes<br>
more capable, it will automate even things like testbench writing (HDL<br>
Coder already does something like this) and support code (like a<br>
Python notebook that creates a solid set of test vectors for a<br>
testbench) and design documents. All of us should be worrying about<br>
some number of tomorrows in the future.<br>
<br>
That day is not yet "today" with Chat GPT, when it comes to writing VHDL.<br>
</blockquote></div>
</blockquote></div></div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div dir="ltr">-Michelle Thompson<br><br><div dir="ltr">"Potestatem obscuri lateris nescis."<br></div><div><br></div></div></div></div></div></div></div></div>