OpenCores
URL https://opencores.org/ocsvn/vhdl_cpu_emulator/vhdl_cpu_emulator/trunk

Subversion Repositories vhdl_cpu_emulator

[/] [vhdl_cpu_emulator/] [trunk/] [cpu_sim.vhd] - Rev 3

Compare with Previous | Blame | View Log

--Mango DSP Ltd. Copyright (C) 2006
--Creator: Nachum Kanovsky
 
library ieee;
use ieee.std_logic_1164.all;
use work.design_top_constants.all;
use std.textio.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
 
entity cpu_sim is
  port(
    fname    : in    filename;
    clk      : out std_logic;
    rstN     : out   std_logic;
    cpu_cs1  : out   std_logic;
    cpu_cs2  : out   std_logic;
    cpu_cs3  : out   std_logic;
    cpu_we   : out   std_logic;
    cpu_a    : out std_logic_vector(4 downto 0);
    cpu_d    : inout std_logic_vector(7 downto 0);
    cpu_irq4 : in    std_logic;
    cpu_irq7 : in    std_logic
    );
end;
 
architecture cpu_sim_simple of cpu_sim is
  signal sig_clk : std_logic := '0';
  shared variable tclk : time    := 0 ns;
  shared variable rl   : integer := 1;
 
  function to_lower (
    constant c : character)
    return character is
  begin  -- to_lower
    if c >= 'A' and c <= 'Z' then
      return character'val(character'pos(c) - character'pos('A') + character'pos('a'));
    else
      return c;
    end if;
  end to_lower;
 
  procedure eat_white (
    variable l : inout line) is
    variable old_l : line := l;
    variable p     : integer;
  begin
    if l = null then
      return;
    end if;
    if l'length = 0 then
      --string is empty
      deallocate(l);
      return;
    end if;
    p := l'left;
    while l'length > p - l'left and (l(p) = ' ' or l(p) = HT) loop
      p := p + 1;
    end loop;
    if p = l'left then
      --no whitespace
      return;
    elsif l'length <= p - l'left then
      --only whitespace - p passed the whole string
      deallocate(l);
    else
      l := new string'(old_l(p to old_l'right));
      deallocate(old_l);
    end if;
  end eat_white;
 
  procedure shrink_line (
    variable l : inout line;
    variable p : inout integer) is
    variable old_l : line := l;
  begin
    assert l /= null report "shrink_line l equals null" severity failure;
    if p = 0 then
      return;
    elsif p = l'length then
      deallocate(l);
    else
      l := new string'(old_l(old_l'left + p + 1 to old_l'right));
      deallocate(old_l);
    end if;
  end shrink_line;
 
  procedure read_word (
    l     : inout line;
    value : inout line) is
    variable size : integer := 0;
    variable p    : integer;
  begin
    if value /= null then
      deallocate(value);
    end if;
    eat_white(l);
    if l = null then
      return;
    end if;
    p := l'left;
    while l'length > p - l'left and (l(p) /= ' ' and l(p) /= HT) loop
      l(p) := to_lower(l(p));
      p    := p + 1;
    end loop;
    p     := p - 1;
    value := new string'(l(l'left to p));
    p     := p + 1 - l'left;
    shrink_line(l, p);
  end read_word;
 
  procedure get_line(
    file f     :       text;
    variable l : inout line) is
  begin
    if l /= null then
      deallocate(l);
    end if;
    loop
      if endfile(f) then
        return;
      end if;
      readline(f, l);
      eat_white(l);
      if l /= null and l(l'left) /= '#' then
        return;
      else
        deallocate(l);
      end if;
    end loop;
  end get_line;
 
  type dfile is record
    fn : line;
    ln : integer;
  end record;
  type dfile_access is access dfile;
 
  procedure readline(
    variable dfa : inout dfile_access;
    l            : inout line) is
    file fl    : text;
    variable c : integer := 0;
  begin
    file_open(fl, dfa.fn.all, read_mode);
    if l /= null then
      deallocate(l);
    end if;
    while c /= dfa.ln loop
      if endfile(fl) then
        if l /= null then
          deallocate(l);
        end if;
        file_close(fl);
        return;
      end if;
      readline(fl, l);
      c := c + 1;
    end loop;
    if endfile(fl) then
      if l /= null then
        deallocate(l);
      end if;
      file_close(fl);
      return;
    end if;
    readline(fl, l);
    file_close(fl);
    dfa.ln := dfa.ln + 1;
  end readline;
 
  --writeline deallocates the line
  procedure write(
    variable fn : in    line;
    variable l  : inout line) is
    file fl        : text;
    file fl_tmp    : text;
    variable l_tmp : line;
  begin
    file_open(fl_tmp, "tmp.txt", write_mode);
    file_open(fl, fn.all, read_mode);
    while not endfile(fl) loop
      readline(fl, l_tmp);
      writeline(fl_tmp, l_tmp);
    end loop;
    l_tmp := new string'(l(l'left to l'right));
    writeline(fl_tmp, l_tmp);
    file_close(fl_tmp);
    file_close(fl);
    file_open(fl_tmp, "tmp.txt", read_mode);
    file_open(fl, fn.all, write_mode);
    while not endfile(fl_tmp) loop
      readline(fl_tmp, l_tmp);
      writeline(fl, l_tmp);
    end loop;
    file_close(fl_tmp);
    file_close(fl);
  end write;
 
  procedure write(
    variable fn : in line;
    variable sl : in std_logic) is
    file fl        : text;
    file fl_tmp    : text;
    variable b     : bit;
    variable l_tmp : line;
  begin
    file_open(fl_tmp, "tmp.txt", write_mode);
    file_open(fl, fn.all, read_mode);
    while not endfile(fl) loop
      readline(fl, l_tmp);
      writeline(fl_tmp, l_tmp);
    end loop;
    if sl = '1' then
      b := '1';
    else
      b := '0';
    end if;
    write(l_tmp, b);
    writeline(fl, l_tmp);
    file_close(fl_tmp);
    file_close(fl);
    file_open(fl_tmp, "tmp.txt", read_mode);
    file_open(fl, fn.all, write_mode);
    while not endfile(fl_tmp) loop
      readline(fl_tmp, l_tmp);
      writeline(fl, l_tmp);
    end loop;
    file_close(fl_tmp);
    file_close(fl);
  end write;
 
  procedure write(
    variable fn   : in line;
    variable slv8 : in std_logic_vector(7 downto 0)) is
    file fl        : text;
    file fl_tmp    : text;
    variable l_tmp : line;
  begin
    file_open(fl_tmp, "tmp.txt", write_mode);
    file_open(fl, fn.all, read_mode);
    while not endfile(fl) loop
      readline(fl, l_tmp);
      writeline(fl_tmp, l_tmp);
    end loop;
    write(l_tmp, to_bitVector(slv8));
    writeline(fl_tmp, l_tmp);
    file_close(fl_tmp);
    file_close(fl);
    file_open(fl_tmp, "tmp.txt", read_mode);
    file_open(fl, fn.all, write_mode);
    while not endfile(fl_tmp) loop
      readline(fl_tmp, l_tmp);
      writeline(fl, l_tmp);
    end loop;
    file_close(fl_tmp);
    file_close(fl);
  end write;
 
  procedure get_line(
    variable dfa : inout dfile_access;
    variable l   : inout line) is
    variable l_temp : line;
  begin
    if l /= null then
      deallocate(l);
    end if;
    loop
      readline(dfa, l_temp);
      if l_temp = null then
        l := null;
        return;
      end if;
      eat_white(l_temp);
      if l_temp /= null and l_temp(l_temp'left) /= '#' then
        l := l_temp;
        return;
      end if;
    end loop;
  end get_line;
 
  type wait_commands is (wt_done, wt_time, wt_irq4, wt_irq7);
 
  type waiter is record
    cmd    : wait_commands;
    tm_end : time;
    v      : std_logic;
  end record;
  type waiter_access is access waiter;
 
  procedure check_wait(
    variable w : inout waiter) is
  begin
    case w.cmd is
      when wt_time =>
        if now >= w.tm_end then
          w.cmd := wt_done;
        end if;
      when wt_irq4 =>
        if cpu_irq4 = w.v then
          w.cmd := wt_done;
        end if;
      when wt_irq7 =>
        if cpu_irq7 = w.v then
          w.cmd := wt_done;
        end if;
      when others => null;
    end case;
  end check_wait;
 
  type var_types is (vt_string, vt_bit, vt_vector8);
  type var;
  type var_access is access var;
  type var_accessx16 is array (15 downto 0) of var_access;
  type var is record
    n    : line;
    vt   : var_types;
    s    : line;
    sl   : std_logic;
    slv8 : std_logic_vector(7 downto 0);
  end record;
  type vars;
  type vars_access is access vars;
  type vars is record
    va16     : var_accessx16;
    next_vsa : vars_access;
  end record;
 
  procedure get_var(
    variable n   : in  line;
    variable vsa : in  vars_access;
    variable va  : out var_access) is
  begin
    if vsa = null then
      return;
    end if;
    va := null;
    for i in vsa.va16'range loop
      if vsa.va16(i) /= null and vsa.va16(i).n.all = n.all then
        va := vsa.va16(i);
        return;
      end if;
    end loop;
    get_var(n, vsa.next_vsa, va);
  end get_var;
 
  procedure add_var(
    variable vsa : inout vars_access;
    variable n   : in    line;
    variable vt  : in    var_types) is
    variable vsa_temp : vars_access;
    variable v_temp   : var_access;
  begin
    vsa_temp     := vsa.next_vsa;
    vsa.next_vsa := null;
    get_var(n, vsa, v_temp);
    vsa.next_vsa := vsa_temp;
    vsa_temp     := null;
    if v_temp /= null then
      return;
    end if;
    for i in vsa.va16'range loop
      if vsa.va16(i) = null then
        vsa.va16(i)    := new var;
        vsa.va16(i).n  := new string'(n(n'left to n'right));
        vsa.va16(i).vt := vt;
        return;
      end if;
    end loop;
    report "too many variables" severity failure;
  end add_var;
 
  procedure add_var(
    variable vsa : inout vars_access;
    variable n   : in    line;
    variable s   : in    line) is
    variable v_temp : var_access;
    variable vt     : var_types;
  begin
    vt       := vt_string;
    add_var(vsa, n, vt);
    get_var(n, vsa, v_temp);
    v_temp.s := new string'(s(s'left to s'right));
  end add_var;
 
  procedure add_var(
    variable vsa : inout vars_access;
    variable n   : in    line;
    variable sl  : in    std_logic) is
    variable v_temp : var_access;
    variable vt     : var_types;
  begin
    vt        := vt_string;
    add_var(vsa, n, vt);
    get_var(n, vsa, v_temp);
    v_temp.sl := sl;
  end add_var;
 
  procedure add_var(
    variable vsa  : inout vars_access;
    variable n    : in    line;
    variable slv8 : in    std_logic_vector(7 downto 0)) is
    variable v_temp : var_access;
    variable vt     : var_types;
  begin
    vt          := vt_string;
    add_var(vsa, n, vt);
    get_var(n, vsa, v_temp);
    v_temp.slv8 := slv8;
  end add_var;
 
  type thread_states is (st_ready, st_done);
  type thread;
  type thread_access is access thread;
  type thread is record
    dfa      : dfile_access;
    ln_start : integer;
    st       : thread_states;
    w        : waiter_access;
    vsa      : vars_access;
    next_tha : thread_access;
  end record;
 
  type tholder;
  type tholder_access is access tholder;
  type tholder is record
    th : thread_access;
    n  : tholder_access;
    p  : tholder_access;
  end record;
 
  procedure init_thread (
    variable tha : inout thread_access;
    variable dfa : in    dfile_access;
    variable ln  : in    integer;
    variable w   : in    waiter_access;
    variable vsa : in    vars_access) is
    variable int : integer;
  begin
    tha.dfa          := dfa;
    tha.ln_start     := ln;
    tha.st           := st_ready;
    tha.w            := w;
    tha.vsa          := new vars;
    tha.vsa.next_vsa := vsa;
    tha.w.cmd        := wt_done;
  end init_thread;
 
  procedure declare_var(
    variable l_type    : inout line;
    variable l_varname : inout line;
    variable vsa       : inout vars_access) is
    variable vt : var_types;
  begin
    assert l_type /= null and l_varname /= null report "declare_var bad parameters" severity failure;
    if l_type.all = "bit" then
      vt := vt_bit;
      add_var(vsa, l_varname, vt);
    elsif l_type.all = "vector8" then
      vt := vt_vector8;
      add_var(vsa, l_varname, vt);
    elsif l_type.all = "string" then
      vt := vt_string;
      add_var(vsa, l_varname, vt);
    else
      report "l_type is not bit, vector8, or string" severity failure;
    end if;
  end declare_var;
 
  procedure var_test(
    variable l_left  : inout line;
    variable l_op    : inout line;
    variable l_right : inout line;
    variable bl_good : inout boolean;
    variable vsa     : inout vars_access) is
    variable va_left  : var_access;
    variable va_right : var_access;
    variable sl       : std_logic;
    variable slv8     : std_logic_vector(7 downto 0);
    variable b        : bit;
    variable bv8      : bit_vector(7 downto 0);
    variable s        : line;
  begin
    assert l_left /= null and l_op /= null and l_right /= null report "var_test invalid null parameters" severity failure;
    get_var(l_left, vsa, va_left);
    assert va_left /= null report "var_test left variable not found" severity failure;
    get_var(l_right, vsa, va_right);
    if va_right /= null then
      assert va_left.vt = va_right.vt report "var_test var types not the same" severity failure;
      case va_right.vt is
        when vt_bit =>
          sl := va_right.sl;
        when vt_vector8 =>
          slv8 := va_right.slv8;
        when vt_string =>
          s := va_right.s;
      end case;
    else
      case va_left.vt is
        when vt_bit =>
          read(l_right, b, bl_good);
          assert bl_good = true report "var_test last parameter failed read" severity failure;
          if b = '1' then
            sl := '1';
          else
            sl := '0';
          end if;
        when vt_vector8 =>
          read(l_right, bv8, bl_good);
          assert bl_good = true report "var_test last parameter failed read" severity failure;
          slv8 := to_stdlogicvector(bv8);
        when vt_string =>
          s := l_right;
      end case;
    end if;
    bl_good := false;
    case va_left.vt is
      when vt_bit =>
        assert l_op.all = "==" or l_op.all = ">" or l_op.all = "<" or l_op.all = "&" or l_op.all = "|" report "var_test invalid operation for bit, use ==,>,<,&,|" severity failure;
        if l_op.all = "==" then
          if va_left.sl = sl then
            bl_good := true;
            return;
          end if;
        elsif l_op.all = ">" then
          if va_left.sl > sl then
            bl_good := true;
            return;
          end if;
        elsif l_op.all = "<" then
          if va_left.sl < sl then
            bl_good := true;
            return;
          end if;
        elsif l_op.all = "&" then
          if (va_left.sl and sl) /= '0' then
            bl_good := true;
            return;
          end if;
        elsif l_op.all = "|" then
          if (va_left.sl or sl) /= '0' then
            bl_good := true;
            return;
          end if;
        end if;
      when vt_vector8 =>
        assert l_op.all = "==" or l_op.all = ">" or l_op.all = "<" or l_op.all = "&" or l_op.all = "|" report "var_test invalid operation for vector8, use ==,>,<,&,|" severity failure;
        if l_op.all = "==" then
          if va_left.slv8 = slv8 then
            bl_good := true;
            return;
          end if;
        elsif l_op.all = ">" then
          if va_left.slv8 > slv8 then
            bl_good := true;
            return;
          end if;
        elsif l_op.all = "<" then
          if va_left.slv8 < slv8 then
            bl_good := true;
            return;
          end if;
        elsif l_op.all = "&" then
          if (va_left.slv8 and slv8) /= "00000000" then
            bl_good := true;
            return;
          end if;
        elsif l_op.all = "|" then
          if (va_left.slv8 or slv8) /= "00000000" then
            bl_good := true;
            return;
          end if;
        end if;
      when vt_string =>
        assert l_op.all = "==" report "var_test string has only == operation" severity failure;
        if va_left.s = s then
          bl_good := true;
          return;
        end if;
      when others => null;
    end case;
  end var_test;
 
--variables are deallocated in this function
  procedure var_op (
    variable l_left  : inout line;
    variable l_op    : inout line;
    variable l_right : inout line;
    variable vsa     : inout vars_access) is
    variable va_left  : var_access;
    variable va_right : var_access;
    variable slv8     : std_logic_vector(7 downto 0);
    variable slv16    : std_logic_vector(15 downto 0);
    variable b        : bit;
    variable bv8      : bit_vector(7 downto 0);
    variable bl_good  : boolean;
  begin
    assert l_left /= null and l_op /= null and l_right /= null report "l_left or l_op or l_right are null" severity failure;
    if l_left.all = "bit" or l_left.all = "vector8" or l_left.all = "string" then
      declare_var(l_left, l_op, vsa);
      l_left := l_op;
      l_op   := null;
      read_word(l_right, l_op);
    end if;
    get_var(l_left, vsa, va_left);
    assert va_left /= null report "variable not found" severity failure;
    case va_left.vt is
      when vt_string =>
        assert l_op.all = "=" report "illegal op, string has only = operation" severity failure;
        if va_left.s /= null then
          deallocate(va_left.s);
        end if;
        get_var(l_right, vsa, va_right);
        if va_right /= null then
          va_left.s := new string'(va_right.s(va_right.s'left to va_right.s'right));
        else
          read_word(l_right, va_left.s);
        end if;
      when vt_bit =>
        assert l_op.all = "=" report "illegal op, bit has only = operation" severity failure;
        get_var(l_right, vsa, va_right);
        if va_right /= null then
          assert va_right.vt = vt_bit report "non bit variable being op'ed with bit variable" severity failure;
          va_left.sl := va_right.sl;
        else
          read(l_right, b, bl_good);
          if bl_good = true then
            if b = '1' then
              va_left.sl := '1';
            else
              va_left.sl := '0';
            end if;
          else
            report "bit operation missing bit value" severity failure;
          end if;
        end if;
      when vt_vector8 =>
        get_var(l_right, vsa, va_right);
        if va_right /= null then
          assert va_right.vt = vt_vector8 report "non vector8 variable being op'ed with vector8 variable" severity failure;
          slv8 := va_right.slv8;
        else
          read(l_right, bv8);
          slv8 := to_stdlogicvector(bv8);
        end if;
        if l_op.all = "=" then
          va_left.slv8 := slv8;
        elsif l_op.all = "+=" then
          va_left.slv8 := va_left.slv8 + slv8;
        elsif l_op.all = "-=" then
          va_left.slv8 := va_left.slv8 - slv8;
        elsif l_op.all = "*=" then
          slv16        := va_left.slv8 * slv8;
          va_left.slv8 := slv16(7 downto 0);
        elsif l_op.all = "&=" then
          va_left.slv8 := va_left.slv8 and slv8;
        elsif l_op.all = "|=" then
          va_left.slv8 := va_left.slv8 or slv8;
        else
          report "illegal op, vector8 has only =, +, -, &, | operations" severity failure;
        end if;
    end case;
    deallocate(l_left);
    deallocate(l_op);
    deallocate(l_right);
  end var_op;
 
  procedure clear(
    variable fn : inout line) is
    file fl : text;
  begin
    file_open(fl, fn.all, write_mode);
    file_close(fl);
  end clear;
 
  procedure find_match (
    variable dfa     : inout dfile_access;
    constant s_open  : in    string;
    constant s_close : in    string) is
    variable l   : line;
    variable cmd : line;
  begin
    get_line(dfa, l);
    read_word(l, cmd);
    while cmd.all /= s_close loop
      if cmd.all = s_open then
        find_match(dfa, s_open, s_close);
      end if;
      get_line(dfa, l);
      read_word(l, cmd);
    end loop;
  end find_match;
 
  procedure find_match (
    variable dfa     : inout dfile_access;
    constant s_open  : in    string;
    constant s_other  : in    string;
    constant s_close : in    string) is
    variable l   : line;
    variable cmd : line;
  begin
    get_line(dfa, l);
    read_word(l, cmd);
    while cmd.all /= s_close and cmd.all /= s_other loop
      if cmd.all = s_open then
        find_match(dfa, s_open, s_close);
      end if;
      get_line(dfa, l);
      read_word(l, cmd);
    end loop;
  end find_match;
 
  procedure read_dma (
    variable l       : inout line;
    variable vsa     : inout vars_access;
    signal   cpu_cs1 : out   std_logic;
    signal   cpu_we  : out   std_logic;
    signal   cpu_a   : out std_logic_vector(4 downto 0);
    signal   cpu_d   : inout std_logic_vector(7 downto 0)) is
    variable l_tmp : line;
    variable va : var_access;
    variable addr : std_logic_vector(7 downto 0);
    variable size : integer;
    variable incr : integer;
    variable bl_good : boolean;
    variable bv8 : bit_vector(7 downto 0);
    variable filename : line;
    variable slv8 : std_logic_vector(7 downto 0);
  begin
    read_word(l, l_tmp);
    assert l_tmp /= null report "read_dma parameter missing" severity failure;
    get_var(l_tmp, vsa, va);
    if va = null then
      read(l_tmp, bv8, bl_good);
      assert bl_good report "read_dma address invalid" severity failure;
      addr := to_stdlogicvector(bv8);
    else
      assert va.vt = vt_vector8 report "read_dma address variable not found" severity failure;
      addr := va.slv8;
    end if;
    read_word(l, l_tmp);
    assert l_tmp /= null report "read_dma parameter missing" severity failure;
    get_var(l_tmp, vsa, va);
    if va = null then
      read(l_tmp, bv8, bl_good);
      assert bl_good report "read_dma size invalid" severity failure;
      size := to_integer(unsigned(to_stdlogicvector(bv8)));
    else
      assert va /= null and va.vt = vt_vector8 report "read_dma size variable not found" severity failure;
      size := to_integer(unsigned(va.slv8));
    end if;
    read_word(l, l_tmp);
    assert l_tmp /= null report "read_dma parameter missing" severity failure;
    get_var(l_tmp, vsa, va);
    if va = null then
      read(l_tmp, bv8, bl_good);
      assert bl_good report "read_dma incr invalid" severity failure;
      incr := to_integer(unsigned(to_stdlogicvector(bv8)));
    else
      assert va /= null and va.vt = vt_vector8 report "read_dma incr variable not found" severity failure;
      incr := to_integer(unsigned(va.slv8));
    end if;
    read_word(l, l_tmp);
    assert l_tmp /= null report "read_dma parameter missing" severity failure;
    filename := l_tmp;
    l_tmp := null;
 
    for i in 0 to size - 1 loop
      if i < (size + rl) then
        cpu_cs1 <= '1';
        cpu_a <= addr(cpu_a'range);
        addr := addr + incr;
      end if;
      if i > rl then
        slv8 := cpu_d;
        write(filename, slv8);
      end if;
      wait for 1 ps;
      wait until rising_edge(sig_clk);
    end loop;
    cpu_cs1 <= '0';
    cpu_a   <= (others => '0');
    for i in 0 to rl - 1 loop
      if (size + i) > rl then
        slv8 := cpu_d;
        write(filename, slv8);
      end if;
      wait for 1 ps;
      wait until rising_edge(sig_clk);
    end loop;
    slv8 := cpu_d;
    write(filename, slv8);
--        cpu_cs1 <= '1';
--        wait for 1 ps;
--        wait until rising_edge(sig_clk);
--        cpu_cs1 <= '0';
--        cpu_a   <= (others => '0');
--        for i in 1 to rl loop
--          --waiting for data to get back
--          wait for 1 ps;
--          wait until rising_edge(sig_clk);
--        end loop;  -- i
--        read_word(l, l_first);
--        if l_first = null then
--          exit;
--        end if;
--        get_var(l_first, tha.vsa, va);
--        assert va /= null and va.vt = vt_vector8 report "illegal address for read" severity failure;
--        va.slv8 := cpu_d;
--        va      := null;
  end read_dma;
 
  procedure process_thread (
    variable tha     : inout thread_access;
    signal   cpu_cs1 : out   std_logic;
    signal   cpu_we  : out   std_logic;
    signal   cpu_a   : out std_logic_vector(4 downto 0);
    signal   cpu_d   : inout std_logic_vector(7 downto 0)) is
    variable va       : var_access;
    variable l        : line;
    variable tm       : time;
    variable b        : bit;
    variable l_first  : line;
    variable l_second : line;
    variable bl_good  : boolean;
    variable bv8      : bit_vector(7 downto 0);
  begin
    while tha.st = st_ready and tha.w.all.cmd = wt_done loop
      if tha.next_tha /= null then
        if tha.next_tha.st = st_done then
          find_match(tha.dfa, "while", "while_end");
          deallocate(tha.next_tha);
        else
          process_thread(tha.next_tha, cpu_cs1, cpu_we, cpu_a, cpu_d);
          exit;
        end if;
      end if;
      if tha.st = st_ready then
        get_line(tha.dfa, l);
        read_word(l, l_first);
      end if;
      tha.st := st_ready;
      if l_first = null then
        tha.st := st_done;
      elsif l_first.all = "wait" then
        read(l, tm);
        tha.w.cmd    := wt_time;
        tha.w.tm_end := tm + now;
        check_wait(tha.w.all);
      elsif l_first.all = "wait_interrupt4" then
        tha.w.cmd := wt_irq4;
        read(l, b, bl_good);
        if bl_good then
          if b = '1' then
            tha.w.v := '1';
          else
            tha.w.v := '0';
          end if;
        else
          tha.w.v := '1';
        end if;
        check_wait(tha.w.all);
      elsif l_first.all = "while" then
        tha.next_tha := new thread;
        init_thread(tha.next_tha, tha.dfa, tha.dfa.ln, tha.w, tha.vsa);
      elsif l_first.all = "while_exit" then
        tha.st := st_done;
      elsif l_first.all = "while_end" then
        tha.dfa.ln := tha.ln_start;
      elsif l_first.all = "if" then
        read_word(l, l_first);
        read_word(l, l_second);
        var_test(l_first, l_second, l, bl_good, tha.vsa);
        if bl_good = false then
          find_match(tha.dfa, "if", "if_else", "if_end");
        end if;
      elsif l_first.all = "if_else" then
        find_match(tha.dfa, "if", "if_end");
      elsif l_first.all = "if_end" then
      elsif l_first.all = "clear" then
        read_word(l, l_first);
        assert l_first /= null report "clear without file or variable name" severity failure;
        get_var(l_first, tha.vsa, va);
        if va /= null then
          assert va.vt = vt_string report "non string variable name" severity failure;
          clear(va.s);
        else
          clear(l_first);
        end if;
        deallocate(l_first);
        va := null;
      elsif l_first.all = "read" then
        cpu_cs1 <= '1';
        read_word(l, l_first);
        assert l_first /= null report "read parameter missing" severity failure;
        get_var(l_first, tha.vsa, va);
        assert va = null or va.vt = vt_vector8 report "illegal address for read" severity failure;
        if va = null then
          read(l_first, bv8);
          cpu_a <= to_stdlogicvector(bv8)(cpu_a'left downto 0);
        else
          cpu_a <= va.slv8(cpu_a'left downto 0);
          va    := null;
        end if;
        --waiting for request to get to cpu block
        wait for 1 ps;
        wait until rising_edge(sig_clk);
        cpu_cs1 <= '0';
        cpu_a   <= (others => '0');
        for i in 1 to rl loop
          --waiting for data to get back
          wait for 1 ps;
          wait until rising_edge(sig_clk);
        end loop;  -- i
        read_word(l, l_first);
        if l_first = null then
          exit;
        end if;
        get_var(l_first, tha.vsa, va);
        assert va /= null and va.vt = vt_vector8 report "illegal address for read" severity failure;
        va.slv8 := cpu_d;
        va      := null;
      elsif l_first.all = "write" then
        cpu_cs1 <= '1';
        cpu_we  <= '1';
        read_word(l, l_first);
        assert l_first /= null report "write parameter missing" severity failure;
        get_var(l_first, tha.vsa, va);
        assert va = null or va.vt = vt_vector8 report "illegal address for write" severity failure;
        if va = null then
          read(l_first, bv8);
          cpu_a <= to_stdlogicvector(bv8)(cpu_a'left downto 0);
        else
          cpu_a <= va.slv8(cpu_a'left downto 0);
          va    := null;
        end if;
        deallocate(l_first);
        read_word(l, l_first);
        assert l_first /= null report "write parameter missing" severity failure;
        get_var(l_first, tha.vsa, va);
        assert va = null or va.vt = vt_vector8 report "illegal data for write" severity failure;
        if va = null then
          read(l_first, bv8);
          cpu_d <= to_stdlogicvector(bv8)(cpu_d'left downto 0);
        else
          cpu_d <= va.slv8(cpu_d'left downto 0);
          va    := null;
        end if;
        deallocate(l_first);
        wait for 1 ps;
        wait until rising_edge(sig_clk);
        cpu_cs1 <= '0';
        cpu_we  <= '0';
        cpu_a   <= (others => '0');
        cpu_d   <= (others => 'Z');
      elsif l_first.all = "read_dma" then
        read_dma(l, tha.vsa, cpu_cs1, cpu_we, cpu_a, cpu_d);
      elsif l_first.all = "write" then
--        write_dma(l, tha.vsa, cpu_cs1, cpu_we, cpu_a, cpu_d);
      elsif l_first.all = "print" then
        read_word(l, l_first);
        assert l_first /= null report "no file or variable name for print" severity failure;
        get_var(l_first, tha.vsa, va);
        if va /= null then
          deallocate(l_first);
          l_first := va.s;
          va      := null;
        end if;
        read_word(l, l_second);
        assert l_second /= null report "no variable name for print" severity failure;
        get_var(l_second, tha.vsa, va);
        l_second := null;
        assert va /= null report "invalid variable for print" severity failure;
        if va.vt = vt_string then
          write(l_first, va.s);
        elsif va.vt = vt_bit then
          write(l_first, va.sl);
        elsif va.vt = vt_vector8 then
          write(l_first, va.slv8);
        end if;
        l_first := null;
        va      := null;
      elsif l_first.all = "breakpoint" then
        deallocate(l_first);
      else
        read_word(l, l_second);
        var_op(l_first, l_second, l, tha.vsa);
      end if;
    end loop;
    deallocate(l);
    deallocate(l_first);
  end process_thread;
 
begin
  sig_clk <= not sig_clk after tclk;
  clk <= sig_clk;
  process
    file fl               : text;
    variable l            : line;
    variable l_params     : line;
    variable tm           : time;
    variable bl_alldone   : boolean;
    variable vsa          : vars_access;
    variable l_first      : line;
    variable l_second     : line;
    variable l_third      : line;
    variable wa           : waiter_access;
    variable dfa          : dfile_access;
    variable tholda_start : tholder_access;
    variable tholda       : tholder_access;
    variable tholda_prev  : tholder_access;
  begin
    rstN    <= '0';
    cpu_cs1 <= '0';
    cpu_cs2 <= '0';
    cpu_cs3 <= '0';
    cpu_we  <= '0';
    cpu_a   <= (others => '0');
    cpu_d   <= (others => 'Z');
    file_open(fl, fname, read_mode);
    vsa     := new vars;
    loop
      get_line(fl, l);
      read_word(l, l_first);
      if l_first = null then
        exit;
      elsif l_first.all = "clock" then
        read(l, tm);
        tclk := tm;
      elsif l_first.all = "reset" then
        read(l, tm);
        wait for tm;
        rstN <= '1';
      elsif l_first.all = "read_latency" then
        read(l, rl);
      elsif l_first.all = "thread" then
        tholda := new tholder;
        if tholda_start = null then
          tholda_start := tholda;
          tholda_prev  := tholda_start;
        else
          tholda_prev.n := tholda;
          tholda_prev   := tholda;
        end if;
        tholda.th := new thread;
        read_word(l, l_second);
        wa        := new waiter;
        dfa       := new dfile;
        dfa.fn    := l_second;
        l_second  := null;
        dfa.ln    := 0;
        init_thread(tholda.th, dfa, dfa.ln, wa, vsa);
        while l_first /= null and l_first.all /= "parameters" loop
          get_line(tholda.th.dfa, l_params);
          read_word(l_params, l_first);
        end loop;
        if l_first /= null and l_first.all = "parameters" then
          loop
            read_word(l_params, l_first);
            if l_first = null then
              exit;
            end if;
            assert l_first.all = "bit" or l_first.all = "vector8" or l_first.all = "string" report "illegal variable type in parameter list" severity failure;
            read_word(l_params, l_second);
            assert l_second /= null report "variable name missing in parameter list" severity failure;
            declare_var(l_first, l_second, tholda.th.vsa);
            deallocate(l_first);
            l_first  := l_second;
            l_second := new string'("=");
            read_word(l, l_third);
            assert l_third /= null report "variable value missing in thread spawn call" severity failure;
            var_op(l_first, l_second, l_third, tholda.th.vsa);
          end loop;
        else
          tholda.th.dfa.ln := 0;
        end if;
        tholda := tholda.n;
      else
        read_word(l, l_second);
        var_op(l_first, l_second, l, vsa);
      end if;
    end loop;
    wait for 1 ps;
    wait until rising_edge(sig_clk);
    loop
      bl_alldone := true;
      tholda     := tholda_start;
      while tholda /= null loop
        if tholda.th.w.cmd /= wt_done then
          check_wait(tholda.th.w.all);
          bl_alldone := false;
        end if;
        tholda := tholda.n;
      end loop;
      tholda      := tholda_start;
      tholda_prev := null;
      while tholda /= null loop
        if tholda.th.w.cmd = wt_done then
          process_thread(tholda.th, cpu_cs1, cpu_we, cpu_a, cpu_d);
          bl_alldone := false;
        end if;
        if tholda.th.st = st_done then
          if tholda_prev /= null then
            tholda_prev.n := tholda.n;
          else
            tholda_start := tholda.n;
          end if;
          deallocate(tholda.th.w);
          deallocate(tholda.th.vsa);
          deallocate(tholda.th.dfa);
          deallocate(tholda.th);
        end if;
        tholda_prev := tholda;
        tholda      := tholda.n;
      end loop;
      wait for 1 ps;
      wait until rising_edge(sig_clk);
      if bl_alldone then
        cpu_cs1 <= '0';
        cpu_we  <= '0';
        cpu_a   <= (others => '0');
        cpu_d   <= (others => 'Z');
        wait;
      end if;
    end loop;
  end process;
end cpu_sim_simple;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.