Commit c03f7a79 authored by Michael Reese's avatar Michael Reese

eb_sim_core: it works now but performance is decreased by the chopper which is…

eb_sim_core: it works now but performance is decreased by the chopper which is needed to talk to the WR-core
parent 7d69ea1e
......@@ -20,17 +20,21 @@ entity simbridge is
end entity;
architecture simulation of simbridge is
signal counter : integer;
signal end_cyc : boolean;
begin
process
variable master_o_cyc,master_o_stb,master_o_we : std_logic;
variable master_o_dat,master_o_adr,master_o_sel : integer;
variable master_o_dat,master_o_adr,master_o_sel,master_o_end_cyc : integer := 0;
variable master_i_ack,master_i_err,master_i_rty,master_i_stall : std_logic;
variable master_i_dat : integer;
variable master_i_dat,master_i_end_cyc : integer := 0;
variable msi_slave_i_cyc,msi_slave_i_stb,msi_slave_i_we : std_logic;
variable msi_slave_i_dat,msi_slave_i_adr,msi_slave_i_sel : integer;
variable msi_slave_o_ack,msi_slave_o_err,msi_slave_o_rty,msi_slave_o_stall : std_logic;
variable msi_slave_o_dat : integer;
constant stop_until_connected : integer := 1;
variable stb_cnt : integer := 0;
variable end_cycle : boolean := false;
begin
master_o.cyc <= '0';
master_o.stb <= '0';
......@@ -48,25 +52,140 @@ begin
while true loop
wait until rising_edge(clk_i);
end_cyc <= end_cycle;
if end_cycle and stb_cnt = 0 then
master_o.cyc <= '0';
master_o.stb <= '0';
end_cycle := false;
wait until rising_edge(clk_i);
end_cyc <= end_cycle;
end if;
eb_simbridge_msi_slave_in(msi_slave_i_cyc,msi_slave_i_stb,msi_slave_i_we,msi_slave_i_adr,msi_slave_i_dat,msi_slave_i_sel);
eb_simbridge_master_out(master_o_cyc,master_o_stb,master_o_we,master_o_adr,master_o_dat,master_o_sel);
eb_simbridge_master_out(master_o_cyc,master_o_stb,master_o_we,master_o_adr,master_o_dat,master_o_sel,master_o_end_cyc);
if master_o_end_cyc /= 0 then
end_cycle := true;
end if;
master_o.cyc <= master_o_cyc;
master_o.stb <= master_o_stb;
master_o.we <= master_o_we;
master_o.adr <= std_logic_vector(to_signed(master_o_adr,32));
master_o.dat <= std_logic_vector(to_signed(master_o_dat,32));
master_o.sel <= std_logic_vector(to_signed(master_o_sel, 4));
--if master_o_stb = '1' and master_o_cyc = '1' and master_i.stall = '0' then
-- report "stb:" & integer'image(master_o_adr);
--end if;
wait until falling_edge(clk_i);
end_cyc <= end_cycle;
master_i_ack := master_i.ack;
master_i_err := master_i.err;
master_i_rty := master_i.rty;
master_i_stall := master_i.stall;
if end_cycle then master_i_stall := '1'; end if;
master_i_dat := to_integer(signed(master_i.dat));
eb_simbridge_master_in(master_i_ack,master_i_err,master_i_rty,master_i_stall,master_i_dat);
if master_o_cyc = '1' and master_o_stb = '1' and master_i_stall = '0' and master_i_ack = '0' then stb_cnt := stb_cnt + 1; end if;
if master_o_cyc = '1' and master_o_stb = '1' and master_i_stall = '1' and master_i_ack = '1' then stb_cnt := stb_cnt - 1; end if;
if master_o_cyc = '1' and master_o_stb = '0' and master_i_ack = '1' then stb_cnt := stb_cnt - 1; end if;
counter <= stb_cnt;
eb_simbridge_master_in(master_i_ack,master_i_err,master_i_rty,master_i_stall,master_i_dat,master_i_end_cyc);
if master_i_end_cyc /= 0 then
end_cycle := true;
end if;
eb_simbridge_msi_slave_out(msi_slave_o_ack,msi_slave_o_err,msi_slave_o_rty,msi_slave_o_stall,msi_slave_o_dat);
if master_i.err = '1' and master_o_cyc = '1' then
report "err:" & integer'image(master_i_dat);
end if;
end loop;
end process;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.simbridge_pkg.all;
entity simbridge_chopper is
port (
clk_i : in std_logic;
rstn_i : in std_logic;
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
master_o : out t_wishbone_master_out;
master_i : in t_wishbone_master_in
);
end entity;
architecture rtl of simbridge_chopper is
signal stall : std_logic := '0';
begin
master_o <= (cyc => slave_i.cyc,
stb => slave_i.stb and not stall,
we => slave_i.we,
sel => slave_i.sel,
adr => slave_i.adr,
dat => slave_i.dat);
slave_o <= (ack => master_i.ack,
err => master_i.err,
rty => master_i.rty,
stall => master_i.stall or stall,
dat => master_i.dat);
process
begin
wait until rising_edge(clk_i);
if stall = '0' and master_i.stall = '0' and slave_i.stb = '1' then
stall <= '1';
elsif master_i.ack = '1' or master_i.err = '1' or master_i.rty = '1' then
--else
stall <= '0';
end if;
end process;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.simbridge_pkg.all;
entity simbridge_chopped is
generic (
g_sdb_address : t_wishbone_address;
g_simbridge_msi : t_sdb_msi := c_simbridge_msi
);
port (
clk_i : in std_logic;
rstn_i : in std_logic;
master_o : out t_wishbone_master_out;
master_i : in t_wishbone_master_in;
msi_slave_i : in t_wishbone_slave_in;
msi_slave_o : out t_wishbone_slave_out
);
end entity;
architecture simulation of simbridge_chopped is
signal master_out : t_wishbone_master_out;
signal master_in : t_wishbone_master_in;
signal slave_out : t_wishbone_slave_out;
signal slave_int : t_wishbone_slave_in;
begin
sb: entity work.simbridge
generic map(g_sdb_address, g_simbridge_msi)
port map(clk_i, rstn_i, master_out, master_in, msi_slave_i, msi_slave_o);
cp: entity work.simbridge_chopper
port map(
clk_i => clk_i,
rstn_i => rstn_i,
slave_i => master_out,
slave_o => master_in,
master_o => master_o,
master_i => master_i);
end architecture;
\ No newline at end of file
......@@ -23,10 +23,10 @@ package simbridge_pkg is
procedure eb_simbridge_init(stop_unitl_connected : in integer; sdb_adr, msi_addr_first, msi_addr_last : in integer);
attribute foreign of eb_simbridge_init: procedure is "VHPIDIRECT eb_simbridge_init";
procedure eb_simbridge_master_out(cyc, stb, we : out std_logic; adr, dat , sel: out integer);
procedure eb_simbridge_master_out(cyc, stb, we : out std_logic; adr, dat , sel, end_cyc: out integer);
attribute foreign of eb_simbridge_master_out : procedure is "VHPIDIRECT eb_simbridge_master_out";
procedure eb_simbridge_master_in(ack, err, rty, stall : in std_logic; dat : in integer);
procedure eb_simbridge_master_in(ack, err, rty, stall : in std_logic; dat : in integer; end_cyc : out integer);
attribute foreign of eb_simbridge_master_in : procedure is "VHPIDIRECT eb_simbridge_master_in";
procedure eb_simbridge_msi_slave_out(ack, err, rty, stall : out std_logic; dat : out integer);
......@@ -44,12 +44,12 @@ package body simbridge_pkg is
assert false report "VHPI" severity failure;
end procedure;
procedure eb_simbridge_master_out(cyc, stb, we : out std_logic; adr, dat , sel: out integer) is
procedure eb_simbridge_master_out(cyc, stb, we : out std_logic; adr, dat , sel, end_cyc: out integer) is
begin
assert false report "VHPI" severity failure;
end procedure;
procedure eb_simbridge_master_in(ack, err, rty, stall : in std_logic; dat : in integer) is
procedure eb_simbridge_master_in(ack, err, rty, stall : in std_logic; dat : in integer; end_cyc : out integer) is
begin
assert false report "VHPI" severity failure;
end procedure;
......
......@@ -180,8 +180,9 @@ public:
}
void master_out(std_logic_t *cyc, std_logic_t *stb, std_logic_t *we, int *adr, int *dat, int *sel) {
int master_out(std_logic_t *cyc, std_logic_t *stb, std_logic_t *we, int *adr, int *dat, int *sel) {
// std::cerr << "out " << state << std::endl;
int end_cyc = 0;
// std::cerr << "control_out" << std::endl;
*cyc = STD_LOGIC_0;
......@@ -231,6 +232,7 @@ public:
}
wb_stbs.push_back(wb_stb(response,response,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().comment = "header";
wb_stbs.back().end_cyc = eb_flag_cyc;
// std::cerr << "header " << std::hex << std::setw(8) << std::setfill('0') << word
// << " response " << std::setw(8) << std::setfill('0') << response << std::endl;
......@@ -254,12 +256,14 @@ public:
uint32_t base_write_adr;
if (next_word(base_write_adr)) {
wb_stbs.push_back(wb_stb(0x0,0x0,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
state = EB_SLAVE_STATE_EB_CONFIG_REST;
}
} else if (eb_rcount > 0) {
uint32_t base_ret_adr;
if (next_word(base_ret_adr)) {
wb_stbs.push_back(wb_stb(base_ret_adr,base_ret_adr,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
state = EB_SLAVE_STATE_EB_CONFIG_REST;
}
} else {
......@@ -273,8 +277,10 @@ public:
--eb_wcount;
if (eb_wcount == 0) {
wb_stbs.push_back(wb_stb(new_header,new_header,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
} else {
wb_stbs.push_back(wb_stb(0x0,0x0,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
}
if (eb_wcount == 0) {
if (eb_rcount == 0) {
......@@ -292,20 +298,25 @@ public:
switch(read_adr) {
case 0x0:
wb_stbs.push_back(wb_stb(error_shift_reg,error_shift_reg,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
error_shift_reg = 0; // clear the error shift register
break;
case 0xc:
// this should return the sdb address
wb_stbs.push_back(wb_stb(eb_sdb_adr,eb_sdb_adr,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
break;
case 0x2c:
wb_stbs.push_back(wb_stb(0x1,0x1,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
break;
case 0x34:
wb_stbs.push_back(wb_stb(eb_msi_adr_first,eb_msi_adr_first,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
break;
case 0x3c:
wb_stbs.push_back(wb_stb(eb_msi_adr_last,eb_msi_adr_last,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
break;
case 0x40: // msi_adr
if (msi_queue.size() > 0) {
......@@ -319,12 +330,15 @@ public:
msi_cnt = 0;
}
wb_stbs.push_back(wb_stb(msi_adr,msi_adr,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
break;
case 0x44: // msi_dat
wb_stbs.push_back(wb_stb(msi_dat,msi_dat,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
break;
case 0x48:
wb_stbs.push_back(wb_stb(msi_cnt,msi_cnt,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
break;
// x"00000000" when "01000", -- 0x20 = 0[010 00]00
......@@ -341,6 +355,7 @@ public:
// x"00000000" when others;
default:
wb_stbs.push_back(wb_stb(0x0,0x0,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
wb_stbs.back().err = true;
}
if (eb_rcount == 0) {
......@@ -355,6 +370,7 @@ public:
if (next_word(base_write_adr)) {
// output_word_buffer.push_back(base_write_adr);
wb_stbs.push_back(wb_stb(0x0,0x0,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
// wb_stbs.back().zero = true;
state = EB_SLAVE_STATE_EB_WISHBONE_REST;
}
......@@ -362,6 +378,7 @@ public:
if (next_word(base_ret_adr)) {
// output_word_buffer.push_back(base_ret_adr);
wb_stbs.push_back(wb_stb(base_ret_adr,base_ret_adr,false,true)); // not a real strobe, just a pass-through
wb_stbs.back().end_cyc = eb_flag_cyc;
state = EB_SLAVE_STATE_EB_WISHBONE_REST;
}
} else {
......@@ -375,6 +392,7 @@ public:
--eb_wcount;
// put the write strobe into the queue
wb_stbs.push_back(wb_stb(base_write_adr,write_val,true));
wb_stbs.back().end_cyc = eb_flag_cyc;
if (eb_wcount == 0) {
wb_stbs.back().new_header = true;
wb_stbs.back().new_header_value = new_header;
......@@ -402,6 +420,7 @@ public:
// << " rcnt " << std::dec << (int)eb_rcount << std::endl;
--eb_rcount;
wb_stbs.push_back(wb_stb(read_adr,0,false));
wb_stbs.back().end_cyc = eb_flag_cyc;
if (eb_rcount == 0) {
state = EB_SLAVE_STATE_EB_HEADER;
}
......@@ -412,7 +431,7 @@ public:
}
handle_pass_through();
if (handle_pass_through()) end_cyc = 1;
send_output_buffer();
if (eb_flag_cyc) {
......@@ -427,6 +446,9 @@ public:
*we = STD_LOGIC_0;
if (wb_stbs.size() > 0) {
strobe = true;
if (wb_stbs.front().end_cyc) {
end_cyc = 1;
}
if (wb_stbs.front().we) {
*we = STD_LOGIC_1;
write_enable = true;
......@@ -439,12 +461,15 @@ public:
}
*stb = strobe ? STD_LOGIC_1 : STD_LOGIC_0;
*we = write_enable ? STD_LOGIC_1 : STD_LOGIC_0;
return end_cyc;
}
void handle_pass_through() {
int handle_pass_through() {
int end_cyc = 0;
// std::cerr << "handle_pass_through " << wb_stbs.size() << std::endl;
while(wb_stbs.size() > 0 && wb_stbs.front().passthrough) {
wb_wait_for_acks.push_back(wb_stbs.front());
if (wb_stbs.front().end_cyc) end_cyc = 1;
wb_stbs.pop_front();
}
// std::cerr << "handle_pass_through " << wb_wait_for_acks.size() << std::endl;
......@@ -457,7 +482,7 @@ public:
wb_wait_for_acks.pop_front();
}
// std::cerr << "handle_pass_through " << output_word_buffer.size() << std::endl;
return end_cyc;
}
void send_output_buffer()
......@@ -491,12 +516,14 @@ public:
}
// should be called on falling_edge(clk)
void master_in(std_logic_t ack, std_logic_t err, std_logic_t rty, std_logic_t stall, int dat) {
int master_in(std_logic_t ack, std_logic_t err, std_logic_t rty, std_logic_t stall, int dat) {
// std::cerr << "in" << std::endl;
// std::cerr << "control_in wb_stbs.size() = " << std::dec << (int)wb_stbs.size() << std::endl;
handle_pass_through();
int end_cyc = 0;
if (handle_pass_through()) end_cyc = 1;
if (wb_stbs.size() > 0 && (strobe && stall == STD_LOGIC_0)) {
wb_wait_for_acks.push_back(wb_stbs.front());
if (wb_stbs.front().end_cyc) end_cyc = 1;
wb_stbs.pop_front();
}
if (wb_wait_for_acks.size() > 0 && (ack == STD_LOGIC_1 || err == STD_LOGIC_1)) {
......@@ -519,7 +546,7 @@ public:
error_shift_reg = (error_shift_reg << 1) | err;
}
send_output_buffer();
return end_cyc;
}
......@@ -609,11 +636,12 @@ private:
bool err;
bool passthrough;
bool zero;
bool end_cyc;
bool new_header;
uint32_t new_header_value;
std::string comment;
wb_stb(uint32_t a, uint32_t d, bool w, bool pt = false)
: adr(a), dat(d), we(w), ack(false), err(false), passthrough(pt), zero(false), new_header(false) {};
: adr(a), dat(d), we(w), ack(false), err(false), passthrough(pt), zero(false), end_cyc(false), new_header(false) {};
};
std::deque<wb_stb> wb_stbs;
std::deque<wb_stb> wb_wait_for_acks;
......@@ -633,19 +661,19 @@ void eb_simbridge_init(int stop_until_connected, int sdb_adr, int msi_addr_first
extern "C"
void eb_simbridge_master_out(char *cyc, char *stb, char *we, int *adr, int *dat, int *sel)
void eb_simbridge_master_out(char *cyc, char *stb, char *we, int *adr, int *dat, int *sel, int *end_cyc)
{
std_logic_t _cyc, _stb, _we;
slave->master_out(&_cyc,&_stb,&_we,adr,dat,sel);
*end_cyc = slave->master_out(&_cyc,&_stb,&_we,adr,dat,sel);
*cyc = (char)_cyc;
*stb = (char)_stb;
*we = (char)_we;
}
extern "C"
void eb_simbridge_master_in(std_logic_t ack, std_logic_t err, std_logic_t rty, std_logic_t stall, int dat)
void eb_simbridge_master_in(std_logic_t ack, std_logic_t err, std_logic_t rty, std_logic_t stall, int dat, int *end_cyc)
{
// std::cerr << "in" << std::endl;
slave->master_in(ack,err,rty,stall,dat);
*end_cyc = slave->master_in(ack,err,rty,stall,dat);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment