<commit_before>library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;

library work;
  use work.functions.all;
  use work.psl.all;
  use work.dma_package.all;

entity dma is
  port (
    i                                                   : in  dma_in;
    o                                                   : out dma_out
  );
end entity dma;

architecture logic of dma is

  signal q, r                                           : dma_int;
  signal re                                             : dma_ext;

  alias write                                           : std_logic is i.r.tag(PSL_TAG_WIDTH - 1);
  alias tag                                             : unsigned(DMA_TAG_WIDTH - 1 downto 0) is i.r.tag(DMA_TAG_WIDTH - 1 downto 0);

begin

  comb : process(all)
    variable v                                          : dma_int;
  begin

----------------------------------------------------------------------------------------------------------------------- default assignments

    v                                                   := r;
    v.read                                              := '0';
    v.read_touch                                        := '0';
    v.write                                             := '0';
    v.write_touch                                       := '0';
    v.o.dc.read.valid                                   := '0';
    v.o.dc.write.valid                                  := '0';

    v.id                                                := r.id + u(i.cd.read.valid or i.cd.write.request.valid);
    v.read_credits                                      := r.read_credits + u(i.r.valid and not(write));
    v.write_credits                                     := r.write_credits + u(i.r.valid and write);
    v.rt.available                                      := not is_full(r.rt.tag, r.rb.pull_address);
    v.wt.available                                      := not is_full(r.wt.tag, r.wb.pull_address);
    v.rse.engine(r.rse.pull_engine).touch.count         := r.rse.engine(r.rse.pull_engine).touch.count + u(r.read and not(r.read_touch));
    v.wse.engine(r.wse.pull_engine).touch.count         := r.wse.engine(r.wse.pull_engine).touch.count + u(r.write and not(r.write_touch));

    if i.b.rad(0) then
      v.o.b.rdata                                       := re.wb.data(1023 downto 512);
    else
      v.o.b.rdata                                       := re.wb.data(511 downto 0);
    end if;

----------------------------------------------------------------------------------------------------------------------- select read/write

    if l(r.rse.active_count > 0 and r.wse.active_count > 0 and v.read_credits > 0 and v.write_credits > 0) and v.rt.available and v.wt.available then
      v.read                                            := not(DMA_WRITE_PRIORITY);
      v.write                                           := DMA_WRITE_PRIORITY;
    elsif v.rt.available and l(r.rse.active_count > 0 and v.read_credits > 0) then
      v.read                                            := '1';
    elsif v.wt.available and l(r.wse.active_count > 0 and v.write_credits > 0) then
      v.write                                           := '1';
    end if;

    if v.read then
      v.o.c.tag                                         := "0" & r.rt.tag(DMA_TAG_WIDTH - 1 downto 0);
    else
      v.o.c.tag                                         := "1" & r.wt.tag(DMA_TAG_WIDTH - 1 downto 0);
    end if;

    v.o.c.valid                                         := v.read or v.write;
    v.read_credits                                      := v.read_credits - u(v.read);
    v.write_credits                                     := v.write_credits - u(v.write);
    v.rt.tag                                            := r.rt.tag + u(v.read);
    v.wt.tag                                            := r.wt.tag + u(v.write);

----------------------------------------------------------------------------------------------------------------------- move requests to stream engines

    for stream in 0 to DMA_READ_ENGINES - 1 loop
      if not(re.rq(stream).empty) and r.rse.free(stream) then
        v.rse.free(stream)                              := '0';
        v.rse.ready(stream)                             := '1';
        v.rse.engine(stream).hold                       := (others => '0');
        v.rse.engine(stream).touch.touch                := '0';
        v.rse.engine(stream).touch.count                := (others => '0');
        v.rse.engine(stream).touch.address              := re.rq(stream).request.address + PSL_PAGESIZE;
        v.rse.engine(stream).request                    := re.rq(stream).request;
      end if;
    end loop;

    for stream in 0 to DMA_WRITE_ENGINES - 1 loop
      if not(re.wq(stream).empty) and r.wse.free(stream) then
        v.wse.free(stream)                              := '0';
        v.wse.ready(stream)                             := '1';
        v.wse.engine(stream).hold                       := (others => '0');
        v.wse.engine(stream).touch.touch                := '0';
        v.wse.engine(stream).touch.count                := (others => '0');
        v.wse.engine(stream).touch.address              := re.wq(stream).request.address + PSL_PAGESIZE;
        v.wse.engine(stream).request                    := re.wq(stream).request;
      end if;
    end loop;

----------------------------------------------------------------------------------------------------------------------- select stream engine

    for stream in 0 to DMA_READ_ENGINES - 1 loop
      if r.rse.ready(stream) and not(r.rse.free(stream)) then
        v.rse.pull_engine                               := stream;
      end if;
    end loop;
    v.rse.pull_stream                                   := (others => '0');
    v.rse.pull_stream(v.rse.pull_engine)                := '1';

    for stream in 0 to DMA_WRITE_ENGINES - 1 loop
      if r.wse.ready(stream) and not(r.wse.free(stream)) and not(re.wqb(stream).empty) then
        v.wse.pull_engine                               := stream;
      end if;
    end loop;
    v.wse.pull_stream                                   := (others => '0');
    v.wse.pull_stream(v.rse.pull_engine)                := '1';

    v.wqb(v.wse.pull_engine)                            := v.wqb(v.wse.pull_engine) - u(v.write and not(v.write_touch));

----------------------------------------------------------------------------------------------------------------------- generate commands

    if v.read then
      if DMA_READ_TOUCH and l(r.rse.engine(v.rse.pull_engine).touch.count = DMA_TOUCH_COUNT and r.rse.engine(v.rse.pull_engine).request.size + DMA_TOUCH_COUNT > PSL_PAGESIZE)
        and not(r.rse.engine(v.rse.pull_engine).touch.touch)
      then
        v.o.c.com                                       := PCO_TOUCH_I;
        v.o.c.ea                                        := r.rse.engine(v.rse.pull_engine).touch.address;
        v.read_touch                                    := '1';
        v.rse.engine(v.rse.pull_engine).touch.touch     := '1';
        v.rse.engine(v.rse.pull_engine).touch.address   := r.rse.engine(v.rse.pull_engine).touch.address + PSL_PAGESIZE;<commit_msg>Fix for multiple write streams<commit_after>library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;

library work;
  use work.functions.all;
  use work.psl.all;
  use work.dma_package.all;

entity dma is
  port (
    i                                                   : in  dma_in;
    o                                                   : out dma_out
  );
end entity dma;

architecture logic of dma is

  signal q, r                                           : dma_int;
  signal re                                             : dma_ext;

  alias write                                           : std_logic is i.r.tag(PSL_TAG_WIDTH - 1);
  alias tag                                             : unsigned(DMA_TAG_WIDTH - 1 downto 0) is i.r.tag(DMA_TAG_WIDTH - 1 downto 0);

begin

  comb : process(all)
    variable v                                          : dma_int;
  begin

----------------------------------------------------------------------------------------------------------------------- default assignments

    v                                                   := r;
    v.read                                              := '0';
    v.read_touch                                        := '0';
    v.write                                             := '0';
    v.write_touch                                       := '0';
    v.o.dc.read.valid                                   := '0';
    v.o.dc.write.valid                                  := '0';

    v.id                                                := r.id + u(i.cd.read.valid or i.cd.write.request.valid);
    v.read_credits                                      := r.read_credits + u(i.r.valid and not(write));
    v.write_credits                                     := r.write_credits + u(i.r.valid and write);
    v.rt.available                                      := not is_full(r.rt.tag, r.rb.pull_address);
    v.wt.available                                      := not is_full(r.wt.tag, r.wb.pull_address);
    v.rse.engine(r.rse.pull_engine).touch.count         := r.rse.engine(r.rse.pull_engine).touch.count + u(r.read and not(r.read_touch));
    v.wse.engine(r.wse.pull_engine).touch.count         := r.wse.engine(r.wse.pull_engine).touch.count + u(r.write and not(r.write_touch));

    if i.b.rad(0) then
      v.o.b.rdata                                       := re.wb.data(1023 downto 512);
    else
      v.o.b.rdata                                       := re.wb.data(511 downto 0);
    end if;

----------------------------------------------------------------------------------------------------------------------- select read/write

    if l(r.rse.active_count > 0 and r.wse.active_count > 0 and v.read_credits > 0 and v.write_credits > 0) and v.rt.available and v.wt.available then
      v.read                                            := not(DMA_WRITE_PRIORITY);
      v.write                                           := DMA_WRITE_PRIORITY;
    elsif v.rt.available and l(r.rse.active_count > 0 and v.read_credits > 0) then
      v.read                                            := '1';
    elsif v.wt.available and l(r.wse.active_count > 0 and v.write_credits > 0) then
      v.write                                           := '1';
    end if;

    if v.read then
      v.o.c.tag                                         := "0" & r.rt.tag(DMA_TAG_WIDTH - 1 downto 0);
    else
      v.o.c.tag                                         := "1" & r.wt.tag(DMA_TAG_WIDTH - 1 downto 0);
    end if;

    v.o.c.valid                                         := v.read or v.write;
    v.read_credits                                      := v.read_credits - u(v.read);
    v.write_credits                                     := v.write_credits - u(v.write);
    v.rt.tag                                            := r.rt.tag + u(v.read);
    v.wt.tag                                            := r.wt.tag + u(v.write);

----------------------------------------------------------------------------------------------------------------------- move requests to stream engines

    for stream in 0 to DMA_READ_ENGINES - 1 loop
      if not(re.rq(stream).empty) and r.rse.free(stream) then
        v.rse.free(stream)                              := '0';
        v.rse.ready(stream)                             := '1';
        v.rse.engine(stream).hold                       := (others => '0');
        v.rse.engine(stream).touch.touch                := '0';
        v.rse.engine(stream).touch.count                := (others => '0');
        v.rse.engine(stream).touch.address              := re.rq(stream).request.address + PSL_PAGESIZE;
        v.rse.engine(stream).request                    := re.rq(stream).request;
      end if;
    end loop;

    for stream in 0 to DMA_WRITE_ENGINES - 1 loop
      if not(re.wq(stream).empty) and r.wse.free(stream) then
        v.wse.free(stream)                              := '0';
        v.wse.ready(stream)                             := '1';
        v.wse.engine(stream).hold                       := (others => '0');
        v.wse.engine(stream).touch.touch                := '0';
        v.wse.engine(stream).touch.count                := (others => '0');
        v.wse.engine(stream).touch.address              := re.wq(stream).request.address + PSL_PAGESIZE;
        v.wse.engine(stream).request                    := re.wq(stream).request;
      end if;
    end loop;

----------------------------------------------------------------------------------------------------------------------- select stream engine

    for stream in 0 to DMA_READ_ENGINES - 1 loop
      if r.rse.ready(stream) and not(r.rse.free(stream)) then
        v.rse.pull_engine                               := stream;
      end if;
    end loop;
    v.rse.pull_stream                                   := (others => '0');
    v.rse.pull_stream(v.rse.pull_engine)                := '1';

    for stream in 0 to DMA_WRITE_ENGINES - 1 loop
      if r.wse.ready(stream) and not(r.wse.free(stream)) and not(re.wqb(stream).empty) then
        v.wse.pull_engine                               := stream;
      end if;
    end loop;
    v.wse.pull_stream                                   := (others => '0');
    v.wse.pull_stream(v.wse.pull_engine)                := '1';

    v.wqb(v.wse.pull_engine)                            := v.wqb(v.wse.pull_engine) - u(v.write and not(v.write_touch));

----------------------------------------------------------------------------------------------------------------------- generate commands

    if v.read then
      if DMA_READ_TOUCH and l(r.rse.engine(v.rse.pull_engine).touch.count = DMA_TOUCH_COUNT and r.rse.engine(v.rse.pull_engine).request.size + DMA_TOUCH_COUNT > PSL_PAGESIZE)
        and not(r.rse.engine(v.rse.pull_engine).touch.touch)
      then
        v.o.c.com                                       := PCO_TOUCH_I;
        v.o.c.ea                                        := r.rse.engine(v.rse.pull_engine).touch.address;
        v.read_touch                                    := '1';
        v.rse.engine(v.rse.pull_engine).touch.touch     := '1';
        v.rse.engine(v.rse.pull_engine).touch.address   := r.rse.engine(v.rse.pull_engine).touch.address + PSL_PAGESIZE;
{'fraction_non_alphanumeric': 0.18807434533268846, 'fraction_numerical': 0.009258619498376287, 'mean_word_length': 0.896240010480807, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 142, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4702941', 'n_tokens_mistral': 4107, 'n_tokens_neox': 3943, 'n_words': 735}